API Endpoints
Complete reference for all available SavvyMoney API endpoints.
Users
Enroll User
Enroll a new user in SavvyMoney. This must be done before accessing credit data.
POST /v1/users/enroll
Request Body:
{
"externalUserId": "user-12345",
"email": "john.doe@example.com",
"firstName": "John",
"lastName": "Doe",
"ssn": "1234",
"dateOfBirth": "1985-06-15",
"address": {
"street": "123 Main St",
"city": "San Francisco",
"state": "CA",
"zipCode": "94102"
},
"phone": "+14155551234"
}
| Field | Type | Required | Description |
|---|---|---|---|
externalUserId | string | Yes | Your internal user ID |
email | string | Yes | User's email address |
firstName | string | Yes | User's first name |
lastName | string | Yes | User's last name |
ssn | string | Yes | Last 4 digits of SSN |
dateOfBirth | string | Yes | Date of birth (YYYY-MM-DD) |
address | object | Yes | User's address |
phone | string | No | Phone number |
Response:
{
"data": {
"userId": "usr_abc123xyz",
"externalUserId": "user-12345",
"status": "pending_verification",
"createdAt": "2024-01-15T10:30:00Z"
}
}
Get User
Retrieve user information.
GET /v1/users/{userId}
Response:
{
"data": {
"userId": "usr_abc123xyz",
"externalUserId": "user-12345",
"email": "john.doe@example.com",
"firstName": "John",
"lastName": "Doe",
"status": "active",
"enrolledAt": "2024-01-15T10:30:00Z",
"lastScoreDate": "2024-01-15"
}
}
Delete User
Remove a user and their data from SavvyMoney.
DELETE /v1/users/{userId}
Response:
{
"data": {
"userId": "usr_abc123xyz",
"deletedAt": "2024-01-15T10:30:00Z",
"message": "User data will be permanently deleted within 30 days"
}
}
Credit Score
Get Credit Score
Retrieve the user's current credit score.
GET /v1/users/{userId}/credit-score
Response:
{
"data": {
"score": 742,
"scoreDate": "2024-01-15",
"scoreRange": {
"min": 300,
"max": 850
},
"rating": "Good",
"bureau": "Equifax",
"factors": [
{
"code": "PAYMENT_HISTORY",
"name": "Payment History",
"impact": "high",
"description": "Your payment history is excellent with no missed payments.",
"score": 95
},
{
"code": "CREDIT_UTILIZATION",
"name": "Credit Utilization",
"impact": "medium",
"description": "You're using 28% of your available credit.",
"score": 72,
"details": {
"utilizationPercent": 28,
"totalBalance": 4200,
"totalLimit": 15000
}
},
{
"code": "CREDIT_AGE",
"name": "Credit Age",
"impact": "medium",
"description": "Your average account age is 6 years.",
"score": 80,
"details": {
"averageAgeYears": 6,
"oldestAccountYears": 12
}
},
{
"code": "CREDIT_MIX",
"name": "Credit Mix",
"impact": "low",
"description": "You have a good mix of credit types.",
"score": 85
},
{
"code": "NEW_CREDIT",
"name": "New Credit Inquiries",
"impact": "low",
"description": "You have 1 recent inquiry.",
"score": 90,
"details": {
"recentInquiries": 1
}
}
],
"trend": {
"direction": "up",
"change": 12,
"period": "3months"
}
}
}
Get Score History
Retrieve historical credit scores.
GET /v1/users/{userId}/credit-score/history
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
months | integer | 12 | Number of months of history |
limit | integer | 25 | Max records to return |
Response:
{
"data": [
{
"score": 742,
"date": "2024-01-15"
},
{
"score": 738,
"date": "2023-12-15"
},
{
"score": 730,
"date": "2023-11-15"
}
],
"pagination": {
"hasMore": true,
"total": 12
}
}
Offers
Get Offers
Retrieve personalized offers for a user.
GET /v1/users/{userId}/offers
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
type | string | - | Filter by offer type (credit_card, loan, mortgage) |
status | string | active | Offer status |
limit | integer | 25 | Max offers to return |
Response:
{
"data": [
{
"offerId": "off_xyz789",
"type": "credit_card",
"provider": "Example Bank",
"name": "Rewards Plus Card",
"description": "Earn 2% cash back on all purchases",
"apr": {
"min": 15.99,
"max": 24.99,
"type": "variable"
},
"creditLimit": {
"min": 5000,
"max": 25000
},
"annualFee": 0,
"signupBonus": {
"amount": 200,
"requirement": "Spend $1,000 in first 3 months"
},
"preQualified": true,
"applicationUrl": "https://offers.savvymoney.com/apply/off_xyz789",
"expiresAt": "2024-02-15T23:59:59Z"
}
],
"pagination": {
"hasMore": false,
"total": 5
}
}
Track Offer Click
Record when a user clicks on an offer.
POST /v1/users/{userId}/offers/{offerId}/click
Request Body:
{
"source": "web",
"timestamp": "2024-01-15T10:30:00Z",
"metadata": {
"page": "dashboard",
"position": 1
}
}
Response:
{
"data": {
"clickId": "clk_abc123",
"offerId": "off_xyz789",
"userId": "usr_abc123xyz",
"recordedAt": "2024-01-15T10:30:00Z"
}
}
Alerts
Get Alerts
Retrieve credit monitoring alerts for a user.
GET /v1/users/{userId}/alerts
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
status | string | all | Filter: unread, read, all |
type | string | - | Filter by alert type |
limit | integer | 25 | Max alerts to return |
Response:
{
"data": [
{
"alertId": "alt_def456",
"type": "score_change",
"title": "Your credit score increased",
"message": "Your credit score went up by 15 points to 742.",
"severity": "info",
"status": "unread",
"createdAt": "2024-01-15T10:30:00Z",
"data": {
"previousScore": 727,
"newScore": 742,
"change": 15
}
},
{
"alertId": "alt_ghi789",
"type": "new_inquiry",
"title": "New credit inquiry detected",
"message": "Example Bank checked your credit report.",
"severity": "warning",
"status": "unread",
"createdAt": "2024-01-14T08:00:00Z",
"data": {
"inquirySource": "Example Bank",
"inquiryDate": "2024-01-14"
}
}
]
}
Alert Types
| Type | Description |
|---|---|
score_change | Credit score changed |
new_inquiry | New credit inquiry |
new_account | New account opened |
account_closed | Account closed |
late_payment | Late payment reported |
high_utilization | Credit utilization exceeded threshold |
address_change | Address change on file |
fraud_alert | Potential fraud detected |
Mark Alert Read
Mark an alert as read.
PATCH /v1/users/{userId}/alerts/{alertId}
Request Body:
{
"status": "read"
}
Identity Verification
Get Verification Questions
Get identity verification questions for a user.
GET /v1/users/{userId}/verification/questions
Response:
{
"data": {
"sessionId": "ver_abc123",
"questions": [
{
"questionId": "q1",
"text": "Which of the following addresses have you lived at?",
"options": [
{ "id": "a", "text": "123 Main St, San Francisco, CA" },
{ "id": "b", "text": "456 Oak Ave, Los Angeles, CA" },
{ "id": "c", "text": "789 Pine Rd, Seattle, WA" },
{ "id": "d", "text": "None of the above" }
]
},
{
"questionId": "q2",
"text": "In which month did you open your account with Example Bank?",
"options": [
{ "id": "a", "text": "January" },
{ "id": "b", "text": "March" },
{ "id": "c", "text": "July" },
{ "id": "d", "text": "I don't have an account with Example Bank" }
]
}
],
"expiresAt": "2024-01-15T10:45:00Z"
}
}
Submit Verification Answers
Submit answers to verification questions.
POST /v1/users/{userId}/verification/answers
Request Body:
{
"sessionId": "ver_abc123",
"answers": [
{ "questionId": "q1", "answerId": "a" },
{ "questionId": "q2", "answerId": "b" }
]
}
Response:
{
"data": {
"verified": true,
"userId": "usr_abc123xyz",
"verifiedAt": "2024-01-15T10:32:00Z"
}
}
Batch Operations
Batch Enroll Users
Enroll multiple users in a single request.
POST /v1/users/enroll/batch
Request Body:
{
"users": [
{
"externalUserId": "user-001",
"email": "user1@example.com",
"firstName": "John",
"lastName": "Doe",
"ssn": "1234",
"dateOfBirth": "1985-06-15",
"address": {
"street": "123 Main St",
"city": "San Francisco",
"state": "CA",
"zipCode": "94102"
}
},
{
"externalUserId": "user-002",
"email": "user2@example.com",
"firstName": "Jane",
"lastName": "Smith",
"ssn": "5678",
"dateOfBirth": "1990-03-22",
"address": {
"street": "456 Oak Ave",
"city": "Los Angeles",
"state": "CA",
"zipCode": "90001"
}
}
]
}
Response:
{
"data": {
"successful": [
{
"externalUserId": "user-001",
"userId": "usr_abc123",
"status": "pending_verification"
}
],
"failed": [
{
"externalUserId": "user-002",
"error": {
"code": "USER_EXISTS",
"message": "User already enrolled"
}
}
]
},
"meta": {
"total": 2,
"successful": 1,
"failed": 1
}
}
Error Responses
All endpoints may return these error responses:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request parameters",
"details": [
{
"field": "email",
"message": "Invalid email format"
}
]
}
}
{
"error": {
"code": "AUTHENTICATION_ERROR",
"message": "Invalid or expired access token"
}
}
{
"error": {
"code": "NOT_FOUND",
"message": "User not found"
}
}
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests",
"retryAfter": 60
}
}
Next Steps
- Configure Webhooks for real-time events
- Review Error Handling
- Implement Security Best Practices