Auth guard: JWT self-access (
jwt.sub == user_id) or any external partner key. Admin key is not accepted — use partner key for programmatic access.Overview
An account links a user to an Account Provider with an external identifier (provider_account_id). All routes are scoped under /users/{user_id}/accounts. Accounts are created with status = pending by default.
The response includes denormalized account_provider_name and account_provider_status from a JOIN — callers don’t need a separate provider lookup.
Account Types
| Value | Description |
|---|---|
savings | Savings bank account |
hsa | Health Savings Account |
education | Education savings account |
Auth Guards by Endpoint
| Endpoint | JWT user | Partner key | Notes |
|---|---|---|---|
POST /users/{user_id}/accounts | ✓ own only | ✓ | Provider must exist and be active |
GET /users/{user_id}/accounts | ✓ own only | ✓ | Filter by status, account_type, account_provider_id |
GET /users/{user_id}/accounts/{id} | ✓ own only | ✓ | |
PATCH /users/{user_id}/accounts/{id} | ✓ own only | ✓ | Only status updatable |
DELETE /users/{user_id}/accounts/{id} | ✓ own only | ✓ | Hard delete |
403 if user_id in the path does not match jwt.sub.
Account Lifecycle
Endpoints
POST /users/{user_id}/accounts
Create a new account. Referenced
account_provider_id must be active.GET /users/{user_id}/accounts
Paginated list. Filter by
status, account_type, or account_provider_id.GET /users/{user_id}/accounts/{id}
Fetch a single account with denormalized provider fields.
PATCH /users/{user_id}/accounts/{id}
Update account
status.DELETE /users/{user_id}/accounts/{id}
Hard delete an account.
Request / Response Examples
Error Codes
| Code | HTTP | Description |
|---|---|---|
AE-800 | 500 | Internal server error |
AE-801 | 404 | Account not found |
AE-802 | 404 | Account provider not found or inactive |
AE-803 | 400 | Validation error |