Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.fyatu.com/llms.txt

Use this file to discover all available pages before exploring further.

Authentication

FYATU API v3.20 uses JWT (JSON Web Tokens) for secure, stateless authentication. Exchange your API credentials for a scoped access token, then use that token to authenticate all V3.20 requests.

Overview

Getting Your Credentials

1

Login to FYATU

Go to FYATU Dashboard and login to your account
2

Open Business Dashboard

Navigate to the Business Dashboard from your account
3

Go to Developer Settings

Click Developer in the left navigation sidebar
4

Get API Credentials

Your businessId is displayed on the page. Generate a secretKey if you haven’t already.
Your secretKey is shown only once when generated. Store it securely — it cannot be recovered. If lost, you must generate a new one (the old key is immediately invalidated).

Token Details

PropertyValue
AlgorithmHS256
Expiry24 hours (86400 seconds)
Refresh windowUp to 5 minutes after expiry
FormatBearer token

Step 1: Obtain Access Token

Exchange your API credentials for a JWT access token. Request only the scopes your integration needs.
curl -X POST https://api.fyatu.com/api/v3.20/auth/token \
  -H "Content-Type: application/json" \
  -d '{
    "businessId": "N1S0W3Q8P0V1E5M6Q4R3D8Z9",
    "secretKey": "sk_biz_your_secret_key_here",
    "grantType": "client_credentials",
    "scopes": ["cards:read", "cards:write", "cardholders:read", "cardholders:write"]
  }'

Response

{
  "success": true,
  "status": 200,
  "message": "Token generated successfully",
  "data": {
    "accessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
    "tokenType": "Bearer",
    "expiresIn": 86400,
    "expiresAt": "2026-05-01T10:30:00+00:00",
    "scopes": ["cards:read", "cards:write", "cardholders:read", "cardholders:write"]
  },
  "meta": {
    "requestId": "req_7af4d2b8e91c35fa4b21890e",
    "timestamp": "2026-04-30T10:30:00+00:00"
  }
}

Step 2: Use Token in Requests

Include the access token in the Authorization header for all V3.20 API requests:
curl -X GET https://api.fyatu.com/api/v3.20/cardholders \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."

Step 3: Refresh Token

Before your token expires, refresh it to get a new one. Refresh is allowed up to 5 minutes after expiry.
curl -X POST https://api.fyatu.com/api/v3.20/auth/refresh \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."

Available Scopes

ScopeGrants Access To
cards:readGET /cards, GET /cards/{id}, GET /cards/{id}/transactions
cards:writePOST /cards, POST /cards/{id}/fund, POST /cards/{id}/freeze, etc.
cardholders:readGET /cardholders, GET /cardholders/{id}
cardholders:writePOST /cardholders, PATCH /cardholders/{id}, DELETE /cardholders/{id}, KYC session
programs:readGET /programs, GET /programs/{id}, GET /programs/{id}/products
account:readGET /account/pricing, GET /account/wallet, GET /account/transactions, GET /account/statement
webhooks:readGET /webhooks, GET /webhooks/events
webhooks:writePUT /webhooks, POST /webhooks/secret/regenerate, POST /webhooks/test
Request only the scopes your integration needs. A read-only dashboard integration should only request *:read scopes. Scopes not requested cannot be used even if you hold the API credentials.

JWT Payload Structure

When decoded, the V3.20 JWT token contains:
{
  "sub":    "N1S0W3Q8P0V1E5M6Q4R3D8Z9",
  "ver":    "3.20",
  "scopes": ["cards:read", "cards:write", "cardholders:read", "cardholders:write"],
  "iat":    1746000000,
  "exp":    1746086400,
  "jti":    "jwt_abc123def456ghi789"
}
ClaimDescription
subBusiness ID (subject)
verAPI version — always "3.20" for V3.20 tokens
scopesArray of granted permissions
iatIssued at (Unix timestamp)
expExpiration (Unix timestamp)
jtiUnique token identifier

Error Responses

Invalid Credentials

{
  "success": false,
  "status": 401,
  "message": "Invalid credentials. Secret key mismatch.",
  "error": { "code": "AUTH_INVALID_CREDENTIALS" },
  "meta": { "requestId": "req_abc123", "timestamp": "2026-04-30T10:30:00+00:00" }
}

Business Not Active

{
  "success": false,
  "status": 401,
  "message": "Business account is not active",
  "error": { "code": "AUTH_BUSINESS_INACTIVE" },
  "meta": { "requestId": "req_abc123", "timestamp": "2026-04-30T10:30:00+00:00" }
}

Invalid Scope Requested

{
  "success": false,
  "status": 400,
  "message": "Invalid scope: collect:write is not available in API v3.20",
  "error": { "code": "VALIDATION_ERROR" },
  "meta": { "requestId": "req_abc123", "timestamp": "2026-04-30T10:30:00+00:00" }
}

Insufficient Scope (on protected endpoint)

{
  "success": false,
  "status": 403,
  "message": "Access denied. Required scope: cards:write",
  "error": { "code": "AUTH_SCOPE_DENIED" },
  "meta": { "requestId": "req_abc123", "timestamp": "2026-04-30T10:30:00+00:00" }
}

Best Practices

  • Store tokens securely in memory or server-side encrypted storage
  • Never expose tokens in client-side code, logs, or public repositories
  • Implement automatic token refresh before expiry
  • Request only the scopes your integration actually needs
  • Use separate tokens for separate microservices (each with its own scope set)
  • A compromised minimal-scope token limits the blast radius
  • Track expiresAt from the token response
  • Refresh when less than 5 minutes remain
  • Handle refresh failures by re-authenticating with your businessId + secretKey
  • On 401 AUTH_TOKEN_INVALID: refresh or re-authenticate
  • On 403 AUTH_SCOPE_DENIED: your token lacks the required scope — request a new token with the correct scopes
  • Always log requestId for debugging with FYATU support

Rate Limits

EndpointRate Limit
POST /v3.20/auth/token10 requests per minute
POST /v3.20/auth/refresh30 requests per minute
Exceeding rate limits returns 429 Too Many Requests. Implement exponential backoff in your retry logic.