> ## 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

> JWT-based authentication for Fyatu API v3. Generate access tokens with your appId and secretKey. Tokens valid for 24 hours with refresh and revoke support.

# Authentication

FYATU API v3 uses JWT (JSON Web Tokens) for secure, stateless authentication. Exchange your app credentials for a short-lived access token, then use that token to authenticate all subsequent requests.

## Overview

```mermaid theme={null}
sequenceDiagram
    participant App as Your App
    participant Auth as FYATU Auth
    participant API as FYATU API

    App->>Auth: POST /v3/auth/token (appId + secretKey)
    Auth-->>App: JWT Access Token
    App->>API: Request with Bearer Token
    API-->>App: API Response
```

## Getting Your Credentials

<Steps>
  <Step title="Login to FYATU">
    Go to [FYATU Dashboard](https://web.fyatu.com) and login to your account
  </Step>

  <Step title="Open Business Console">
    Navigate to the **Business Console** from your dashboard
  </Step>

  <Step title="Select Your App">
    Click on your **Collection App** or **Issuing App** depending on which APIs you need
  </Step>

  <Step title="Get API Keys">
    Go to **Settings** tab, then click **API Keys & Credentials**
  </Step>
</Steps>

## App Types & Scopes

Your access token's scopes depend on the app type:

| App Type           | Available APIs       | Scopes                                                               |
| ------------------ | -------------------- | -------------------------------------------------------------------- |
| **Collection App** | Collections, Payouts | `collect:write`, `collect:read`, `payout:write`, `payout:read`       |
| **Issuing App**    | Cards, Cardholders   | `cards:write`, `cards:read`, `cardholders:write`, `cardholders:read` |

## Token Lifecycle

| Property       | Value                        |
| -------------- | ---------------------------- |
| Token Type     | JWT (HS256)                  |
| Token Expiry   | 24 hours                     |
| Refresh Window | Up to 5 minutes after expiry |
| Token Format   | Bearer token                 |

## Step 1: Obtain Access Token

Exchange your app credentials for a JWT access token:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.fyatu.com/api/v3/auth/token \
    -H "Content-Type: application/json" \
    -d '{
      "appId": "DD123FR45446CECES",
      "secretKey": "your_secret_key_here",
      "grantType": "client_credentials"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.fyatu.com/api/v3/auth/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      appId: 'DD123FR45446CECES',
      secretKey: 'your_secret_key_here',
      grantType: 'client_credentials'
    })
  });

  const data = await response.json();
  const accessToken = data.data.accessToken;
  ```

  ```php PHP theme={null}
  $ch = curl_init('https://api.fyatu.com/api/v3/auth/token');
  curl_setopt_array($ch, [
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_POST => true,
      CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
      CURLOPT_POSTFIELDS => json_encode([
          'appId' => 'DD123FR45446CECES',
          'secretKey' => 'your_secret_key_here',
          'grantType' => 'client_credentials'
      ])
  ]);

  $response = json_decode(curl_exec($ch), true);
  $accessToken = $response['data']['accessToken'];
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.fyatu.com/api/v3/auth/token',
      json={
          'appId': 'DD123FR45446CECES',
          'secretKey': 'your_secret_key_here',
          'grantType': 'client_credentials'
      }
  )

  data = response.json()
  access_token = data['data']['accessToken']
  ```
</CodeGroup>

### Response

```json theme={null}
{
  "success": true,
  "status": 200,
  "message": "Token generated successfully",
  "data": {
    "accessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJERDEyM0ZSNDQ0NjZDRUNFUyIsImJ1cyI6Ik4xUzBXM1E4UDBWMUU1TTZRNFIzRDhaOSIsInR5cGUiOiJjb2xsZWN0aW9uIiwic2NvcGVzIjpbImNvbGxlY3Q6d3JpdGUiLCJjb2xsZWN0OnJlYWQiLCJwYXlvdXQ6d3JpdGUiLCJwYXlvdXQ6cmVhZCJdLCJpYXQiOjE3MzYwNzU4MDAsImV4cCI6MTczNjE2MjIwMCwianRpIjoiand0XzdhZjRkMmI4ZTkxYzM1ZmE0YjIxODkwZSJ9.x2kPqR7mN5vL8wT3fA9sD6gH1jK4cB0eW7yU2iO3pVn",
    "tokenType": "Bearer",
    "expiresIn": 86400,
    "expiresAt": "2026-01-06T10:30:00+00:00",
    "appType": "collection",
    "scopes": ["collect:write", "collect:read", "payout:write", "payout:read"]
  },
  "meta": {
    "requestId": "req_7af4d2b8e91c35fa4b21890e",
    "timestamp": "2026-01-05T10:30:00+00:00"
  }
}
```

## Step 2: Use Token in Requests

Include the access token in the `Authorization` header for all API requests:

```bash theme={null}
curl -X GET https://api.fyatu.com/api/v3/collections \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
```

## Step 3: Refresh Token (Optional)

Before your token expires, you can refresh it to get a new token. Refresh is allowed up to 5 minutes after expiry.

```bash theme={null}
curl -X POST https://api.fyatu.com/api/v3/auth/refresh \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
```

### Response

```json theme={null}
{
  "success": true,
  "status": 200,
  "message": "Token refreshed successfully",
  "data": {
    "accessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJERDEyM0ZSNDQ0NjZDRUNFUyIsImJ1cyI6Ik4xUzBXM1E4UDBWMUU1TTZRNFIzRDhaOSIsInR5cGUiOiJjb2xsZWN0aW9uIiwic2NvcGVzIjpbImNvbGxlY3Q6d3JpdGUiLCJjb2xsZWN0OnJlYWQiLCJwYXlvdXQ6d3JpdGUiLCJwYXlvdXQ6cmVhZCJdLCJpYXQiOjE3MzYxNjIyMDAsImV4cCI6MTczNjI0ODYwMCwianRpIjoiand0XzhjZTk1YTRmMWIzZDY3ZWEyYzA5NDU4ZiJ9.m8nK3pW6rY1qL5vJ0hS9dF2gB4eA7xC3wU8tZ0iV5oR",
    "tokenType": "Bearer",
    "expiresIn": 86400,
    "expiresAt": "2026-01-07T10:30:00+00:00",
    "appType": "collection",
    "scopes": ["collect:write", "collect:read", "payout:write", "payout:read"]
  },
  "meta": {
    "requestId": "req_8ce95a4f1b3d67ea2c09458f",
    "timestamp": "2026-01-06T10:30:00+00:00"
  }
}
```

## Error Responses

### Invalid Credentials

```json theme={null}
{
  "success": false,
  "status": 401,
  "message": "Invalid credentials. Secret key mismatch.",
  "error": {
    "code": "AUTH_INVALID_CREDENTIALS"
  },
  "meta": {
    "requestId": "req_abc123def456",
    "timestamp": "2026-01-05T10:30:00+00:00"
  }
}
```

### Token Expired

```json theme={null}
{
  "success": false,
  "status": 401,
  "message": "Invalid or expired token",
  "error": {
    "code": "AUTH_TOKEN_INVALID"
  },
  "meta": {
    "requestId": "req_abc123def456",
    "timestamp": "2026-01-05T10:30:00+00:00"
  }
}
```

### Insufficient Scope

```json theme={null}
{
  "success": false,
  "status": 403,
  "message": "Access denied. Required scope: cards:write",
  "error": {
    "code": "AUTH_SCOPE_DENIED"
  },
  "meta": {
    "requestId": "req_abc123def456",
    "timestamp": "2026-01-05T10:30:00+00:00"
  }
}
```

## JWT Payload Structure

When decoded, the JWT token contains:

```json theme={null}
{
  "sub": "DD123FR45446CECES",
  "bus": "BUS_xxxxxxxxxxxx",
  "type": "collection",
  "scopes": ["collect:write", "collect:read", "payout:write", "payout:read"],
  "iat": 1704451800,
  "exp": 1704455400,
  "jti": "jwt_xxxxxxxxxxxxxxxxxxxx"
}
```

| Claim    | Description                          |
| -------- | ------------------------------------ |
| `sub`    | App ID (subject)                     |
| `bus`    | Business ID                          |
| `type`   | App type (`collection` or `issuing`) |
| `scopes` | Array of granted permissions         |
| `iat`    | Issued at timestamp                  |
| `exp`    | Expiration timestamp                 |
| `jti`    | Unique token identifier              |

## Best Practices

<AccordionGroup>
  <Accordion title="Token Storage">
    * Store tokens securely in memory or encrypted storage
    * Never expose tokens in client-side code or logs
    * Implement automatic token refresh before expiry
  </Accordion>

  <Accordion title="Token Refresh Strategy">
    * Check token expiry before each request
    * Refresh when less than 5 minutes remain
    * Handle refresh failures by re-authenticating
  </Accordion>

  <Accordion title="Error Handling">
    * Catch 401 errors and re-authenticate
    * Catch 403 errors and check required scopes
    * Log request IDs for debugging with FYATU support
  </Accordion>
</AccordionGroup>

## Rate Limits

Authentication endpoints have the following rate limits:

| Endpoint                | Rate Limit             |
| ----------------------- | ---------------------- |
| `POST /v3/auth/token`   | 10 requests per minute |
| `POST /v3/auth/refresh` | 30 requests per minute |

<Warning>
  Exceeding rate limits will result in a `429 Too Many Requests` response. Implement exponential backoff in your retry logic.
</Warning>
