API Authentication
Sznd API uses JWT (JSON Web Token) authentication for system-to-system API access. After authenticating with your credentials, you'll receive a JWT access token that must be included in all subsequent API requests.
Overview
The authentication flow is straightforward:
- Login - Send your email and password to
/auth/loginto receive a JWT access token - Authenticate Requests - Include the JWT token in the
Authorizationheader of all API requests - Refresh Token - When your access token expires, use the refresh token to get a new access token
Login Endpoint
Authenticate with your email and password to receive JWT tokens.
Request
Endpoint: POST /api/v1/auth/login
Headers:
Content-Type: application/jsonRequest Body:
{
"email": "your-email@example.com",
"password": "your-password",
"device_meta": {
"device_id": "optional-device-id",
"device_name": "optional-device-name"
}
}Parameters:
email(required) - Your registered email addresspassword(required) - Your account passworddevice_meta(optional) - Device information for device tracking and security
Response
Success Response (200 OK):
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "refresh_token_987654321",
"expires_in": 900.0,
"customer": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "your-email@example.com",
"first_name": "John",
"last_name": "Doe",
"role": "USER",
"is_email_verified": true,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
},
"onboarding_statuses": {
"onboarding_completed": true,
"footprint_onboarding_completed": true,
"blaaiz_onboarding_completed": false,
"bridge_onboarding_completed": false,
"borderless_onboarding_completed": false
}
}Response Fields:
access_token- JWT access token (valid for 15 minutes by default)refresh_token- Token used to obtain new access tokensexpires_in- Token expiration time in seconds (typically 900 seconds / 15 minutes)customer- Your user informationonboarding_statuses- Status of various onboarding processes
Error Responses:
400 Bad Request- Invalid request format or missing required fields401 Unauthorized- Invalid email or password202 Accepted- New device detected (if device_meta is provided), additional verification may be required
Example: cURL
curl -X POST /api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "your-email@example.com",
"password": "your-password"
}'Example: HTTP Request
POST /api/v1/auth/login HTTP/1.1
Host: api.sznd.app
Content-Type: application/json
{
"email": "your-email@example.com",
"password": "your-password"
}Using the JWT Token
Once you have the access token, include it in the Authorization header of all authenticated API requests.
Authorization Header Format
Authorization: Bearer <your-access-token>Example: Authenticated Request
curl -X GET /api/v1/quotes \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."Example: HTTP Request
GET /api/v1/quotes HTTP/1.1
Host: api.sznd.app
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/jsonToken Expiration
Access tokens expire after 15 minutes (900 seconds). When a token expires, you'll receive a 401 Unauthorized response. Use the refresh token to obtain a new access token without requiring the user to log in again.
Refresh Token Endpoint
Refresh your access token using a valid refresh token.
Request
Endpoint: POST /api/v1/auth/refresh-token
Headers:
Content-Type: application/jsonRequest Body:
{
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"refresh_token": "your-refresh-token"
}Parameters:
user_id(required) - Your user UUIDrefresh_token(required) - The refresh token received from the login endpoint
Response
Success Response (200 OK):
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "new_refresh_token_987654321",
"expires_in": 900
}Example: cURL
curl -X POST /api/v1/auth/refresh-token \
-H "Content-Type: application/json" \
-d '{
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"refresh_token": "your-refresh-token"
}'Example: HTTP Request
POST /api/v1/auth/refresh-token HTTP/1.1
Host: api.sznd.app
Content-Type: application/json
{
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"refresh_token": "your-refresh-token"
}Error Handling
Common Authentication Errors
| Status Code | Error | Description |
|---|---|---|
400 | Bad Request | Invalid request format or missing required fields |
401 | Unauthorized | Invalid credentials, expired token, or invalid token |
403 | Forbidden | Valid token but insufficient permissions |
429 | Too Many Requests | Too many failed login attempts, account temporarily locked |
Error Response Format
{
"error": "Invalid credentials",
"message": "The email or password you entered is incorrect"
}Handling Token Expiration
When you receive a 401 Unauthorized response, your access token has expired. Refresh it and retry the request:
# Step 1: Refresh the token
curl -X POST /api/v1/auth/refresh-token \
-H "Content-Type: application/json" \
-d '{
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"refresh_token": "your-refresh-token"
}'
# Step 2: Use the new access token in your original request
curl -X GET /api/v1/quotes \
-H "Authorization: Bearer <new-access-token>"Security Best Practices
- Never expose tokens in code repositories - Store tokens securely in environment variables or secret management systems
- Use HTTPS only - Always make API requests over HTTPS to protect tokens in transit
- Handle token expiration - Implement automatic token refresh to ensure uninterrupted API access
- Store tokens securely - Use secure storage mechanisms appropriate for your infrastructure (e.g., environment variables, secret managers)
- Rotate tokens regularly - Use refresh tokens to obtain new access tokens periodically
- Validate tokens - Always validate token expiration before making API requests
- Use service accounts - For system-to-system authentication, use dedicated service accounts rather than user credentials
Next Steps
- Learn about Webhook Authentication for verifying webhook signatures
- Explore the Quotes API to start making transactions
- Review the API Reference for all available endpoints