# API Reference

Complete API documentation for integrating MakaPay into your application.

***

## Base URL

```
Production: https://app.makapay.io/api
```

***

## Authentication

All API requests require authentication via API key.

### Obtaining an API Key

1. Log in to the [MakaPay Dashboard](https://app.makapay.io/dashboard)
2. Navigate to **API Keys**
3. Click **Create New Key**
4. Copy and securely store your API key

### Using the API Key

Include the API key in the `x-api-key` header:

```
x-api-key: YOUR_API_KEY
```

**Important**: Never expose your API key in client-side code.

***

## Endpoints

### Create Payment

Create a new payment link.

```
POST /payments
```

#### Request Body

| Field                | Type    | Required | Description                                                                                                                                                                                                                                                     |
| -------------------- | ------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `merchant`           | string  | Yes      | Ethereum address to receive payment                                                                                                                                                                                                                             |
| `chainId`            | string  | Yes      | Target blockchain chain ID                                                                                                                                                                                                                                      |
| `token`              | string  | Yes      | Token contract address. For ERC-20 tokens, use the contract address. For native tokens (ETH, BNB, MATIC), use the zero address: `0x0000000000000000000000000000000000000000`. See [Supported Networks & Tokens](#supported-networks--tokens) for the full list. |
| `amount`             | string  | Yes      | Payment amount (human-readable, e.g., "100.00")                                                                                                                                                                                                                 |
| `orderId`            | string  | Yes      | Your internal order reference (max 100 chars)                                                                                                                                                                                                                   |
| `description`        | string  | No       | Payment description (max 200 chars)                                                                                                                                                                                                                             |
| `redirectUrl`        | string  | No       | URL to redirect payer after payment. Payment ID appended as `?makapay=ID` (max 2000 chars)                                                                                                                                                                      |
| `expiresAt`          | number  | No       | Unix timestamp (ms) when payment expires. Shows countdown timer to payer.                                                                                                                                                                                       |
| `blockConfirmations` | number  | No       | Required confirmations (default: 1, max: 100)                                                                                                                                                                                                                   |
| `gasless`            | boolean | No       | Enable gasless mode (default: false). **Note:** Only works with stablecoins (USDT, USDC, DAI) or tokens with a known price. Automatically converts to `false` for non-stablecoins without a price.                                                              |
| `payerCoversFee`     | boolean | No       | Payer covers fees (default: false)                                                                                                                                                                                                                              |
| `customPriceUsd`     | string  | No       | USD price per token for [custom tokens](/guides/custom-tokens.md) (e.g., "0.00001234"). Used as fallback if Alchemy and TrustedOracle have no price. Required for tokens with no automatic price source.                                                        |

#### Example Request (ERC-20 Token)

```bash
curl -X POST https://app.makapay.io/api/payments \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "merchant": "0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00",
    "chainId": "137",
    "token": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
    "amount": "50.00",
    "orderId": "order-12345",
    "description": "Premium subscription",
    "blockConfirmations": 1,
    "gasless": false,
    "payerCoversFee": false
  }'
```

#### Example Request (Native Token)

Accept payment in ETH on Ethereum mainnet by passing the zero address as `token`:

```bash
curl -X POST https://app.makapay.io/api/payments \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "merchant": "0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00",
    "chainId": "1",
    "token": "0x0000000000000000000000000000000000000000",
    "amount": "0.5",
    "orderId": "order-67890",
    "description": "Payment in ETH"
  }'
```

#### Response

```json
{
  "url": "https://app.makapay.io/pay/01234567-89ab-cdef-0123-456789abcdef"
}
```

#### Response Fields

| Field | Type   | Description                             |
| ----- | ------ | --------------------------------------- |
| `url` | string | Payment page URL to share with customer |

#### Error Responses

| Status | Error                    | Description                                  |
| ------ | ------------------------ | -------------------------------------------- |
| 400    | Invalid form data        | Request validation failed                    |
| 401    | Unauthorized             | Invalid or missing API key                   |
| 503    | Oracle price unavailable | Price oracle temporarily unavailable (retry) |
| 500    | Failed to create payment | Internal server error                        |

***

### List Payments

List the merchant's payments, newest first, with cursor pagination.

```
GET /v1/payments
```

Authentication: `x-api-key` header **or** an active dashboard session cookie.

#### Query Parameters

| Param           | Type                       | Default | Description                                                                                                                                                                                                                       |
| --------------- | -------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `limit`         | integer (1–100)            | `100`   | Page size.                                                                                                                                                                                                                        |
| `cursor`        | string                     | —       | Opaque cursor returned by the previous page (`nextCursor`). Omit on the first request.                                                                                                                                            |
| `status`        | enum                       | —       | Filter by payment status. One of: `pending`, `paid`, `completed`, `failed`, `expired`, `cancelled`, `withdrawing`, `withdrawn`, `awaiting_gas`, `deploying_wallet`, `withdraw_request`, `waiting_for_confirmation`, `sanctioned`. |
| `createdAfter`  | ISO 8601 string \| Unix ms | —       | Inclusive lower bound on `createdAt`. Combine with `createdBefore` for a range.                                                                                                                                                   |
| `createdBefore` | ISO 8601 string \| Unix ms | —       | Inclusive upper bound on `createdAt`. Must be `>= createdAfter` when both are set.                                                                                                                                                |
| `orderId`       | string                     | —       | Exact-match filter (case-sensitive) on the merchant-supplied `orderId`. Useful for investigating a specific payment.                                                                                                              |

#### Example Request

```bash
curl "https://app.makapay.io/api/v1/payments?limit=50&status=completed" \
  -H "x-api-key: YOUR_API_KEY"
```

Walking the cursor:

```bash
# page 1
curl "https://app.makapay.io/api/v1/payments?limit=100" -H "x-api-key: $KEY"
# page 2 — feed nextCursor back as ?cursor=
curl "https://app.makapay.io/api/v1/payments?limit=100&cursor=<nextCursor>" -H "x-api-key: $KEY"
# repeat until hasMore == false
```

#### Response

```json
{
  "data": [
    {
      "paymentId": "01H...",
      "orderId": "ORDER-123",
      "description": "Invoice #42",
      "status": "completed",
      "createdAt": 1715000000000,
      "completedAt": 1715000060000,
      "expiresAt": 1715003600000,
      "chainId": "8453",
      "token": {
        "address": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
        "symbol": "USDC",
        "decimals": 6
      },
      "amount": "10.00",
      "merchant": "0xMerchant...",
      "recipientAddress": "0xWallet...",
      "transaction": {
        "hash": "0xabc...",
        "blockNumber": 12345678,
        "confirmations": 1
      },
      "fees": {
        "platformFee": "0.10",
        "gasFee": "0.01",
        "processingFee": "0.10",
        "totalFee": "0.21",
        "feePercentage": 1
      },
      "gasless": false,
      "payerCoversFee": false,
      "terminal": {
        "terminalId": "term_aZ3kLm9NqP",
        "code": "R1",
        "name": "Register 1"
      }
    }
  ],
  "nextCursor": "eyJ...",
  "hasMore": true
}
```

#### Response Fields

| Field             | Type           | Description                                                                                                                                                                                                                                                                                                                                               |
| ----------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data[]`          | array          | Payments on this page, newest first.                                                                                                                                                                                                                                                                                                                      |
| `data[].terminal` | object \| null | POS terminal info when the payment was created on a terminal (the `orderId` is `POS-{CODE}-{CASHIER}-{TS}`). `terminalId` is the stable identifier you should store; `code` is the short code embedded in `orderId`; `name` is the dashboard display name. `null` for regular payment-link payments and for POS payments whose terminal has been deleted. |
| `nextCursor`      | string \| null | Pass as `?cursor=` on the next request. `null` when no more pages.                                                                                                                                                                                                                                                                                        |
| `hasMore`         | boolean        | `true` while more pages remain.                                                                                                                                                                                                                                                                                                                           |

#### More Examples

```bash
# Date range — payments created in March 2026
curl "https://app.makapay.io/api/v1/payments?createdAfter=2026-03-01T00:00:00Z&createdBefore=2026-03-31T23:59:59Z" \
  -H "x-api-key: $KEY"

# Date range with Unix ms
curl "https://app.makapay.io/api/v1/payments?createdAfter=1761955200000&createdBefore=1764547199000" \
  -H "x-api-key: $KEY"

# Investigate a specific orderId
curl "https://app.makapay.io/api/v1/payments?orderId=ORDER-12345" \
  -H "x-api-key: $KEY"

# All payments from a specific POS terminal — filter client-side on `terminal.terminalId`
curl "https://app.makapay.io/api/v1/payments?status=completed&limit=100" \
  -H "x-api-key: $KEY" \
  | jq '.data[] | select(.terminal.terminalId == "term_aZ3kLm9NqP")'
```

#### Error Responses

| Status | code             | When                                                                      |
| ------ | ---------------- | ------------------------------------------------------------------------- |
| 400    | `invalid_query`  | Query parameter failed validation (e.g. unknown `status`, `limit > 100`). |
| 401    | `unauthorized`   | No session and no valid API key.                                          |
| 500    | `internal_error` | Unexpected server failure.                                                |

Error envelope:

```json
{ "error": "Unauthorized", "code": "unauthorized" }
```

***

### Get Balance

Get your Gas Tank balance.

```
GET /balance
```

#### Example Request

```bash
curl https://app.makapay.io/api/balance \
  -H "x-api-key: YOUR_API_KEY"
```

#### Response

```json
{
  "balance": "25.500000"
}
```

#### Response Fields

| Field     | Type   | Description                                   |
| --------- | ------ | --------------------------------------------- |
| `balance` | string | Current Gas Tank balance in USDT (6 decimals) |

***

### Verify Payment Redirect

Verify that a payment redirect is authentic. Use this after receiving a redirect from MakaPay to confirm the payment was actually completed.

```
GET /payments/verify?id=PAYMENT_ID&hash=HASH
```

**Note:** This endpoint does not require authentication, as the hash serves as verification.

#### Query Parameters

| Parameter | Type   | Required | Description                                        |
| --------- | ------ | -------- | -------------------------------------------------- |
| `id`      | string | Yes      | The payment ID from the redirect (`makapay` param) |
| `hash`    | string | Yes      | The verification hash from the redirect            |

#### Example Request

```bash
curl "https://app.makapay.io/api/payments/verify?id=01234567-89ab-cdef&hash=abc123..."
```

#### Success Response

```json
{
  "valid": true,
  "verified": true,
  "payment": {
    "paymentId": "01234567-89ab-cdef-0123-456789abcdef",
    "orderId": "order-12345",
    "status": "completed",
    "amount": "50.00",
    "receivedAmount": "50.00",
    "token": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
    "chainId": 137,
    "merchant": "0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00",
    "transactionHash": "0x...",
    "completedAt": 1705312200000
  }
}
```

#### Response Fields

| Field                 | Type    | Description                                                   |
| --------------------- | ------- | ------------------------------------------------------------- |
| `valid`               | boolean | Whether the hash is valid                                     |
| `verified`            | boolean | Whether hash is valid AND payment is completed                |
| `payment`             | object  | Payment details (only if valid)                               |
| `payment.completedAt` | number  | Unix timestamp when payment was completed (only if completed) |
| `error`               | string  | Error message (only if invalid)                               |

#### Error Responses

| Status | Error              | Description                      |
| ------ | ------------------ | -------------------------------- |
| 400    | Missing payment ID | No `id` parameter provided       |
| 400    | Missing hash       | No `hash` parameter provided     |
| 400    | Invalid hash       | Hash does not match payment data |
| 404    | Payment not found  | Payment ID does not exist        |

***

## Redirect Verification Flow

When you configure a `redirectUrl` for a payment, MakaPay will redirect the payer to your URL after successful payment with these query parameters:

```
https://yoursite.com/success?makapay=PAYMENT_ID&success=true&hash=HASH
```

### Query Parameters

| Parameter | Description                                             |
| --------- | ------------------------------------------------------- |
| `makapay` | The unique payment ID                                   |
| `success` | Always `"true"` (redirect only happens on success)      |
| `hash`    | HMAC-SHA256 signature (server-signed, cannot be forged) |

### Security

The `hash` parameter is an HMAC-SHA256 signature computed with a server-side secret. This ensures:

* **Attackers cannot forge redirect URLs** - The secret is never exposed
* **Merchants must verify via API** - Only MakaPay's server can validate the signature

> **Important:** Always verify redirects using the `/api/payments/verify` endpoint. Never trust redirect parameters alone.

### Verification Steps

1. **Extract parameters** from the redirect URL
2. **Call the verify endpoint** to confirm authenticity:

   ```
   GET /api/payments/verify?id={makapay}&hash={hash}
   ```
3. **Check the response**:
   * `verified: true` = Payment is complete and authentic
   * `verified: false` = Do not trust the redirect

### Example Implementation (Node.js)

```javascript
app.get('/payment/success', async (req, res) => {
  const { makapay, hash } = req.query;

  // ALWAYS verify with MakaPay API - never trust redirect params alone
  const response = await fetch(
    `https://app.makapay.io/api/payments/verify?id=${makapay}&hash=${hash}`
  );
  const result = await response.json();

  if (result.verified) {
    // Payment confirmed! Update your order
    await updateOrder(result.payment.orderId, 'paid');
    res.render('success', { payment: result.payment });
  } else {
    // Invalid redirect - possible fraud attempt
    res.status(400).render('error', { message: 'Payment verification failed' });
  }
});
```

***

## Payment Expiration

You can set an expiration time on payment links to create urgency or limit the validity period. When a payment expires, the payer will see an "Expired" status instead of being able to pay.

### How It Works

1. **Set expiration** when creating a payment using the `expiresAt` field (Unix timestamp in milliseconds)
2. **Countdown timer** is shown to the payer on the payment page
3. **Automatic expiration** - a background job checks and expires payments every minute
4. **Grace period** - payments already received are processed even if the link expires

### Common Expiration Durations

| Duration | Calculation                                  |
| -------- | -------------------------------------------- |
| 1 hour   | `Date.now() + 3600000`                       |
| 24 hours | `Date.now() + 86400000`                      |
| 7 days   | `Date.now() + 604800000`                     |
| Custom   | `new Date('2025-01-20T12:00:00Z').getTime()` |

### Example: Payment with 1-Hour Expiration

```bash
curl -X POST https://app.makapay.io/api/payments \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "merchant": "0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00",
    "chainId": "137",
    "token": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
    "amount": "50.00",
    "orderId": "flash-sale-001",
    "description": "Flash sale - limited time offer",
    "expiresAt": '"$(node -e "console.log(Date.now() + 3600000)")"',
    "gasless": true
  }'
```

### Example: Dynamic Expiration (Node.js)

```javascript
async function createTimeLimitedPayment(order, hoursValid = 24) {
  const expiresAt = Date.now() + (hoursValid * 60 * 60 * 1000);

  const response = await fetch('https://app.makapay.io/api/payments', {
    method: 'POST',
    headers: {
      'x-api-key': API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      merchant: '0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00',
      chainId: '137',
      token: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',
      amount: order.total.toString(),
      orderId: order.id,
      description: order.description,
      expiresAt: expiresAt,  // Payment expires in X hours
      gasless: true,
    }),
  });

  return response.json();
}

// Create a payment that expires in 1 hour
const payment = await createTimeLimitedPayment(order, 1);
```

### Payment States After Expiration

| Status      | Description                                          |
| ----------- | ---------------------------------------------------- |
| `expired`   | Payment link expired before any payment was received |
| `completed` | Payment was received before expiration and processed |
| `pending`   | Payment partially received, may still be processed   |

### Best Practices

1. **Use expiration for time-sensitive offers** - flash sales, limited-time discounts
2. **Allow reasonable time** - consider timezone differences and payment processing time
3. **Communicate clearly** - show expiration time in your UI before redirecting to payment
4. **Handle expired state** - provide a way for customers to request a new payment link

***

## Public Endpoints

The following endpoints are **public** and do not require authentication. They are useful for resolving token information before creating a payment.

### Get Token Price

Look up the current USD price for any token. The price is resolved using a two-step waterfall:

1. **Alchemy** — checked first using `chainId` + `address`. Works for most popular tokens on major chains.
2. **TrustedOracle** — fallback if Alchemy has no price. The oracle looks up prices by symbol, so the optional `symbol` parameter is needed for this fallback to work. If you omit `symbol` and Alchemy doesn't have the price, the endpoint returns 404.

```
GET /tokens/price
```

**Note:** This endpoint does not require authentication.

#### Query Parameters

| Parameter | Type   | Required | Description                                                                                                                                                                                                           |
| --------- | ------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `chainId` | string | Yes      | Blockchain chain ID (e.g., `1` for Ethereum, `137` for Polygon)                                                                                                                                                       |
| `address` | string | Yes      | Token contract address (checksummed or lowercase)                                                                                                                                                                     |
| `symbol`  | string | No       | Token symbol (e.g., `ETH`, `BNB`). Only needed for the TrustedOracle fallback — if Alchemy already has a price for this token, the symbol is not used. Pass it when you want full coverage across both price sources. |

#### Example Request

```bash
# With symbol — enables both Alchemy and oracle fallback
curl "https://app.makapay.io/api/tokens/price?chainId=1&address=0xdAC17F958D2ee523a2206206994597C13D831ec7&symbol=USDT"

# Without symbol — Alchemy only, no oracle fallback
curl "https://app.makapay.io/api/tokens/price?chainId=1&address=0xdAC17F958D2ee523a2206206994597C13D831ec7"
```

#### Response

```json
{
  "chainId": 1,
  "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
  "symbol": "USDT",
  "priceUsd": "0.999847",
  "source": "alchemy",
  "timestamp": "2026-02-21T12:00:00.000Z"
}
```

#### Response Fields

| Field       | Type           | Description                                          |
| ----------- | -------------- | ---------------------------------------------------- |
| `chainId`   | number         | The chain ID queried                                 |
| `address`   | string         | Token contract address (lowercased)                  |
| `symbol`    | string \| null | Token symbol (uppercased), or `null` if not provided |
| `priceUsd`  | string         | USD price as a human-readable decimal string         |
| `source`    | string         | Price source used: `"alchemy"` or `"trusted_oracle"` |
| `timestamp` | string         | ISO 8601 timestamp of the response                   |

#### Error Responses

| Status | Error                              | Description                             |
| ------ | ---------------------------------- | --------------------------------------- |
| 400    | chainId and address are required   | Missing required parameters             |
| 400    | chainId must be a number           | Invalid chain ID format                 |
| 400    | Invalid token address              | Address is not a valid Ethereum address |
| 404    | Price not available for this token | No price source could resolve a price   |
| 500    | Failed to fetch token price        | Internal server error                   |

***

### Get Token Metadata

Resolve token metadata (name, symbol, decimals, logo) for any ERC-20 token. Uses Alchemy metadata with on-chain contract read as fallback.

```
GET /tokens/metadata
```

**Note:** This endpoint does not require authentication.

#### Query Parameters

| Parameter | Type   | Required | Description            |
| --------- | ------ | -------- | ---------------------- |
| `chainId` | string | Yes      | Blockchain chain ID    |
| `address` | string | Yes      | Token contract address |

#### Example Request

```bash
curl "https://app.makapay.io/api/tokens/metadata?chainId=137&address=0xc2132D05D31c914a87C6611C10748AEb04B58e8F"
```

#### Response

```json
{
  "name": "Tether USD",
  "symbol": "USDT",
  "decimals": 6,
  "logo": "https://static.alchemyapi.io/images/assets/825.png",
  "hasAlchemyPrice": true,
  "priceUsd": "0.999847",
  "address": "0xc2132d05d31c914a87c6611c10748aeb04b58e8f",
  "chainId": 137
}
```

#### Response Fields

| Field             | Type                | Description                                     |
| ----------------- | ------------------- | ----------------------------------------------- |
| `name`            | string \| null      | Token name from metadata                        |
| `symbol`          | string \| null      | Token ticker symbol                             |
| `decimals`        | number              | Token decimals (e.g., 6 for USDT, 18 for ETH)   |
| `logo`            | string \| null      | URL to the token logo image                     |
| `hasAlchemyPrice` | boolean             | Whether Alchemy has a price feed for this token |
| `priceUsd`        | string \| undefined | Current USD price if available from Alchemy     |
| `address`         | string              | Token contract address (lowercased)             |
| `chainId`         | number              | The chain ID queried                            |

#### Error Responses

| Status | Error                            | Description                                                            |
| ------ | -------------------------------- | ---------------------------------------------------------------------- |
| 400    | chainId and address are required | Missing required parameters                                            |
| 400    | chainId must be a number         | Invalid chain ID format                                                |
| 400    | Invalid token address            | Address is not a valid Ethereum address                                |
| 400    | Cannot read token contract       | Contract doesn't exist at this address/chain or is not an ERC-20 token |
| 500    | Failed to fetch token metadata   | Internal server error                                                  |

***

### Get Oracle Price

Fetch the price of a token directly from the MakaPay TrustedOracle smart contract on MakaChain. This is the same oracle used internally for gas fee calculations and as the fallback in the `/tokens/price` waterfall.

Unlike `/tokens/price` (which resolves by chain + address), this endpoint resolves by **symbol only** — it does not need a chain ID or contract address. Use this when you already know the token symbol and just need its USD price.

```
GET /oracle/price
```

**Note:** This endpoint does not require authentication.

#### Query Parameters

| Parameter | Type   | Required | Description                                                                                                 |
| --------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------- |
| `symbol`  | string | Yes      | Token symbol (e.g., `ETH`, `BNB`, `USDT`). Case-insensitive. `USDT0` is automatically normalized to `USDT`. |

#### Example Request

```bash
curl "https://app.makapay.io/api/oracle/price?symbol=ETH"
```

#### Response

```json
{
  "symbol": "ETH",
  "priceRaw": "2735420000000000000000",
  "priceUsd": "2735.42",
  "decimals": 18
}
```

#### Response Fields

| Field      | Type   | Description                                                  |
| ---------- | ------ | ------------------------------------------------------------ |
| `symbol`   | string | Normalized token symbol (uppercased)                         |
| `priceRaw` | string | Raw price as a big integer string (18 decimals of precision) |
| `priceUsd` | string | USD price as a human-readable decimal string                 |
| `decimals` | number | Precision of `priceRaw` (always `18`)                        |

#### Error Responses

| Status | Error                            | Description                                   |
| ------ | -------------------------------- | --------------------------------------------- |
| 400    | Symbol parameter is required     | Missing `symbol` query parameter              |
| 404    | Price not available for {SYMBOL} | Oracle has no price registered for this token |
| 500    | Failed to fetch price            | Internal server error                         |

#### Supported Symbols

The oracle supports all tokens that have been registered by the MakaPay operator. Common symbols include:

| Symbol  | Description                       |
| ------- | --------------------------------- |
| `ETH`   | Ethereum                          |
| `BNB`   | BNB (Binance Smart Chain)         |
| `MATIC` | Polygon                           |
| `USDT`  | Tether USD (also matches `USDT0`) |
| `USDC`  | USD Coin                          |
| `XRP`   | XRP                               |
| `TRX`   | Tron                              |
| `MAKA`  | MAKA Token                        |

***

## Supported Networks & Tokens

### Mainnet

#### Ethereum (Chain ID: 1)

| Token | Contract Address                             | Decimals | Type       |
| ----- | -------------------------------------------- | -------- | ---------- |
| ETH   | `0x0000000000000000000000000000000000000000` | 18       | Native     |
| USDT  | `0xdAC17F958D2ee523a2206206994597C13D831ec7` | 6        | Stablecoin |
| USDC  | `0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48` | 6        | Stablecoin |
| MAKA  | `0x9FF7B37b84C05DfB08b4f50ADb17a80a3FEfD6eD` | 18       | Token      |

#### Polygon (Chain ID: 137)

| Token | Contract Address                             | Decimals | Type       |
| ----- | -------------------------------------------- | -------- | ---------- |
| MATIC | `0x0000000000000000000000000000000000000000` | 18       | Native     |
| USDT0 | `0xc2132D05D31c914a87C6611C10748AEb04B58e8F` | 6        | Stablecoin |
| USDC  | `0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359` | 6        | Stablecoin |

#### BNB Smart Chain (Chain ID: 56)

| Token | Contract Address                             | Decimals | Type       |
| ----- | -------------------------------------------- | -------- | ---------- |
| BNB   | `0x0000000000000000000000000000000000000000` | 18       | Native     |
| USDT  | `0x55d398326f99059ff775485246999027b3197955` | 18       | Stablecoin |
| USDC  | `0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d` | 18       | Stablecoin |
| XRP   | `0x1d2f0da169ceb9fc7b3144628db156f3f6c60dbe` | 18       | Token      |
| TRX   | `0xce7de646e7208a4ef112cb6ed5038fa6cc6b12e3` | 6        | Token      |

#### Base (Chain ID: 8453)

| Token | Contract Address                             | Decimals | Type       |
| ----- | -------------------------------------------- | -------- | ---------- |
| ETH   | `0x0000000000000000000000000000000000000000` | 18       | Native     |
| USDC  | `0x833589fcd6edb6e08f4c7c32d4f71b54bda02913` | 6        | Stablecoin |

#### Arbitrum One (Chain ID: 42161)

| Token | Contract Address                             | Decimals | Type       |
| ----- | -------------------------------------------- | -------- | ---------- |
| ETH   | `0x0000000000000000000000000000000000000000` | 18       | Native     |
| USDT  | `0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9` | 6        | Stablecoin |
| USDC  | `0xaf88d065e77c8cC2239327C5EDb3A432268e5831` | 6        | Stablecoin |

#### MakaChain (Chain ID: 777178)

| Token | Contract Address                             | Decimals | Type       |
| ----- | -------------------------------------------- | -------- | ---------- |
| USDT  | `0x30C28E393E0732335235685B345c95E6465Ad8A5` | 6        | Stablecoin |
| USDC  | `0x1C978Ed2de920eA6c5844d011Ab9f574979F82A6` | 6        | Stablecoin |

> **Native tokens** use the zero address (`0x000...000`). When creating a payment with a native token, pass the zero address as the `token` parameter.

### Testnet

#### Sepolia (Chain ID: 11155111)

| Token | Contract Address                             | Decimals | Type       |
| ----- | -------------------------------------------- | -------- | ---------- |
| ETH   | `0x0000000000000000000000000000000000000000` | 18       | Native     |
| USDT  | `0x3B62e45fB977773c2eF0404d80e0C59de22A97ec` | 6        | Stablecoin |
| USDC  | `0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238` | 6        | Stablecoin |

#### MakaChain Testnet (Chain ID: 777177)

| Token | Contract Address                             | Decimals | Type       |
| ----- | -------------------------------------------- | -------- | ---------- |
| USDT  | `0x309F410f92A98e43E1EEF623015a2e784F80ed72` | 6        | Stablecoin |
| USDC  | `0x1C978Ed2de920eA6c5844d011Ab9f574979F82A6` | 6        | Stablecoin |

***

## Webhooks

Configure webhooks to receive real-time payment notifications.

### Setup

1. Go to **Dashboard > Webhooks**
2. Enter your webhook URL (HTTPS required)
3. Save configuration

### Webhook Payload

```json
{
  "event": "payment.completed",
  "paymentId": "01234567-89ab-cdef-0123-456789abcdef",
  "orderId": "order-12345",
  "status": "completed",
  "amount": "50.00",
  "receivedAmount": "50.00",
  "token": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
  "chainId": 137,
  "merchant": "0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00",
  "transactionHash": "0x...",
  "timestamp": "2024-01-15T10:30:00Z"
}
```

### Event Types

| Event               | Description                  |
| ------------------- | ---------------------------- |
| `payment.completed` | Payment successfully settled |
| `payment.failed`    | Settlement failed            |
| `payment.expired`   | Payment link expired         |

### Retry Policy

* Failed deliveries are retried up to 3 times
* Retry intervals: 1 minute, 5 minutes, 30 minutes
* View delivery logs in the dashboard

***

## Code Examples

### Node.js

```javascript
const axios = require('axios');

const API_KEY = 'your_api_key';
const BASE_URL = 'https://app.makapay.io/api';

async function createPayment(orderData) {
  const response = await axios.post(
    `${BASE_URL}/payments`,
    {
      merchant: '0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00',
      chainId: '137',
      token: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',
      amount: orderData.total.toString(),
      orderId: orderData.id,
      description: `Order #${orderData.id}`,
    },
    {
      headers: {
        'x-api-key': API_KEY,
        'Content-Type': 'application/json',
      },
    }
  );

  return response.data.url;
}

// Usage
const paymentUrl = await createPayment({
  id: 'order-12345',
  total: 99.99,
});
console.log('Payment URL:', paymentUrl);
```

### Python

```python
import requests

API_KEY = 'your_api_key'
BASE_URL = 'https://app.makapay.io/api'

def create_payment(order_data):
    response = requests.post(
        f'{BASE_URL}/payments',
        json={
            'merchant': '0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00',
            'chainId': '137',
            'token': '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',
            'amount': str(order_data['total']),
            'orderId': order_data['id'],
            'description': f"Order #{order_data['id']}",
        },
        headers={
            'x-api-key': API_KEY,
            'Content-Type': 'application/json',
        }
    )
    response.raise_for_status()
    return response.json()['url']

# Usage
payment_url = create_payment({
    'id': 'order-12345',
    'total': 99.99,
})
print(f'Payment URL: {payment_url}')
```

### PHP

```php
<?php
$api_key = 'your_api_key';
$base_url = 'https://app.makapay.io/api';

function createPayment($orderData) {
    global $api_key, $base_url;

    $ch = curl_init();

    curl_setopt_array($ch, [
        CURLOPT_URL => "$base_url/payments",
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_HTTPHEADER => [
            "x-api-key: $api_key",
            "Content-Type: application/json",
        ],
        CURLOPT_POSTFIELDS => json_encode([
            'merchant' => '0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00',
            'chainId' => '137',
            'token' => '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',
            'amount' => (string)$orderData['total'],
            'orderId' => $orderData['id'],
            'description' => "Order #{$orderData['id']}",
        ]),
    ]);

    $response = curl_exec($ch);
    curl_close($ch);

    $data = json_decode($response, true);
    return $data['url'];
}

// Usage
$paymentUrl = createPayment([
    'id' => 'order-12345',
    'total' => 99.99,
]);
echo "Payment URL: $paymentUrl\n";
```

***

## Rate Limits

| Endpoint                            | Rate Limit                  |
| ----------------------------------- | --------------------------- |
| `POST /payments`                    | 100 requests/minute         |
| `GET /balance`                      | 60 requests/minute          |
| Vault config endpoints              | 100 requests/minute         |
| `POST /vault/v1/users`              | 100 requests/minute         |
| `GET /vault/v1/deposits`            | 100 requests/minute         |
| `GET /vault/v1/business/:id/tokens` | 60 requests/minute (per IP) |

Exceeding rate limits returns HTTP 429 (Too Many Requests).

***

## Error Handling

### Error Response Format

```json
{
  "error": "Error message describing what went wrong"
}
```

### Common Errors

| Status | Error                            | Solution                                                |
| ------ | -------------------------------- | ------------------------------------------------------- |
| 400    | Invalid Merchant address format  | Verify the merchant address is a valid Ethereum address |
| 400    | Invalid Token address format     | Verify the token contract address                       |
| 400    | Invalid network selected         | Use a supported chain ID                                |
| 400    | Amount must be a positive number | Ensure amount is > 0                                    |
| 401    | Unauthorized                     | Check your API key                                      |
| 503    | Oracle price unavailable         | Retry after a few seconds                               |

***

## Vault Configuration API

Configure your vault account, manage accepted tokens, and set up webhooks — all via the API. These endpoints require authentication via the `x-api-key` header.

For an overview of the Vault system, see the [Vault System guide](/guides/vault.md).

***

### Setup Vault

Create a new vault account. Call this once to initialize your vault.

```
POST /vault/v1/config
```

#### Request Body

| Field           | Type   | Required | Description                                |
| --------------- | ------ | -------- | ------------------------------------------ |
| `businessName`  | string | Yes      | Your business display name                 |
| `walletAddress` | string | Yes      | EVM address where processed funds are sent |
| `enabledTokens` | array  | No       | Initial tokens to enable (see below)       |

Each item in `enabledTokens`:

| Field         | Type   | Required | Description                 |
| ------------- | ------ | -------- | --------------------------- |
| `chainId`     | number | Yes      | Blockchain chain ID         |
| `token`       | string | Yes      | Token contract address      |
| `tokenSymbol` | string | Yes      | Token symbol (max 20 chars) |

#### Example Request

```bash
curl -X POST https://app.makapay.io/api/vault/v1/config \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "businessName": "My Casino",
    "walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00",
    "enabledTokens": [
      {
        "chainId": 137,
        "token": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
        "tokenSymbol": "USDT"
      }
    ]
  }'
```

#### Response (201 Created)

```json
{
  "success": true,
  "data": {
    "publicId": "biz_abc123def456",
    "businessName": "My Casino",
    "walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00",
    "feeBps": 25,
    "isActive": true,
    "enabledTokens": [
      {
        "chainId": 137,
        "tokenSymbol": "USDT",
        "tokenAddress": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F"
      }
    ]
  }
}
```

#### Error Responses

| Status | Error                     | Description                                    |
| ------ | ------------------------- | ---------------------------------------------- |
| 400    | businessName is required  | Missing business name                          |
| 400    | walletAddress is required | Missing wallet address                         |
| 400    | Invalid EVM address       | Wallet address is not a valid Ethereum address |
| 401    | Unauthorized              | Missing or invalid API key                     |
| 409    | Vault already configured  | Vault already exists for this API key          |

***

### Get Vault Configuration

Retrieve your current vault configuration.

```
GET /vault/v1/config
```

#### Example Request

```bash
curl https://app.makapay.io/api/vault/v1/config \
  -H "x-api-key: YOUR_API_KEY"
```

#### Response

```json
{
  "success": true,
  "data": {
    "publicId": "biz_abc123def456",
    "businessName": "My Casino",
    "walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00",
    "feeBps": 25,
    "isActive": true,
    "enabledTokens": [
      {
        "chainId": 137,
        "tokenSymbol": "USDT",
        "tokenAddress": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F"
      }
    ]
  }
}
```

#### Error Responses

| Status | Error                | Description                      |
| ------ | -------------------- | -------------------------------- |
| 401    | Unauthorized         | Missing or invalid API key       |
| 404    | Vault not configured | No vault exists for this API key |

***

### Update Vault Settings

Update your vault's business name, wallet address, or active status.

```
PATCH /vault/v1/config
```

#### Request Body

All fields are optional — include only what you want to change.

| Field           | Type    | Required | Description                            |
| --------------- | ------- | -------- | -------------------------------------- |
| `businessName`  | string  | No       | New business name                      |
| `walletAddress` | string  | No       | New wallet address (valid EVM address) |
| `isActive`      | boolean | No       | Enable/disable the vault               |

#### Example Request

```bash
curl -X PATCH https://app.makapay.io/api/vault/v1/config \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "businessName": "Casino Royale",
    "isActive": true
  }'
```

#### Response

```json
{
  "success": true,
  "data": {
    "businessName": "Casino Royale",
    "walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00",
    "isActive": true
  }
}
```

#### Error Responses

| Status | Error                | Description                      |
| ------ | -------------------- | -------------------------------- |
| 400    | Invalid EVM address  | New wallet address is invalid    |
| 401    | Unauthorized         | Missing or invalid API key       |
| 404    | Vault not configured | No vault exists for this API key |

***

### Add Token

Enable a new token for deposits on your vault.

```
POST /vault/v1/config/tokens
```

#### Request Body

| Field                   | Type   | Required | Description                        |
| ----------------------- | ------ | -------- | ---------------------------------- |
| `chainId`               | number | Yes      | Blockchain chain ID (1–999999999)  |
| `token`                 | string | Yes      | Token contract address             |
| `tokenSymbol`           | string | Yes      | Token ticker symbol (max 20 chars) |
| `minDepositAmountCents` | number | No       | Minimum deposit in USD cents       |
| `maxDepositAmountCents` | number | No       | Maximum deposit in USD cents       |

#### Example Request

```bash
curl -X POST https://app.makapay.io/api/vault/v1/config/tokens \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": 56,
    "token": "0x55d398326f99059ff775485246999027b3197955",
    "tokenSymbol": "USDT",
    "minDepositAmountCents": 100,
    "maxDepositAmountCents": 1000000
  }'
```

#### Response (201 Created)

```json
{
  "success": true,
  "data": {
    "chainId": 56,
    "tokenSymbol": "USDT",
    "tokenAddress": "0x55d398326f99059ff775485246999027b3197955"
  }
}
```

#### Error Responses

| Status | Error                   | Description                        |
| ------ | ----------------------- | ---------------------------------- |
| 400    | chainId is required     | Missing chain ID                   |
| 400    | tokenSymbol is required | Missing token symbol               |
| 400    | tokenSymbol too long    | Symbol exceeds 20 characters       |
| 401    | Unauthorized            | Missing or invalid API key         |
| 404    | Vault not configured    | No vault exists for this API key   |
| 409    | Token already enabled   | Token already exists on this chain |

***

### Remove Token

Remove a token from your vault's accepted list.

```
DELETE /vault/v1/config/tokens
```

#### Request Body

| Field     | Type   | Required | Description                     |
| --------- | ------ | -------- | ------------------------------- |
| `chainId` | number | Yes      | Chain ID of the token to remove |
| `token`   | string | Yes      | Token contract address          |

#### Example Request

```bash
curl -X DELETE https://app.makapay.io/api/vault/v1/config/tokens \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": 56,
    "token": "0x55d398326f99059ff775485246999027b3197955"
  }'
```

#### Response

```json
{
  "success": true,
  "data": {
    "removedToken": "USDT",
    "removedChainId": 56,
    "remainingTokens": [
      {
        "chainId": 137,
        "tokenSymbol": "USDT",
        "tokenAddress": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F"
      }
    ]
  }
}
```

#### Error Responses

| Status | Error                          | Description                      |
| ------ | ------------------------------ | -------------------------------- |
| 400    | chainId and token are required | Missing required fields          |
| 401    | Unauthorized                   | Missing or invalid API key       |
| 404    | Token not found                | Token is not in the enabled list |

***

### Get Webhook Configuration

Retrieve your current webhook settings.

```
GET /vault/v1/config/webhooks
```

#### Example Request

```bash
curl https://app.makapay.io/api/vault/v1/config/webhooks \
  -H "x-api-key: YOUR_API_KEY"
```

#### Response

```json
{
  "success": true,
  "data": {
    "url": "https://yoursite.com/webhook/vault",
    "events": ["deposit.completed", "deposit.failed"],
    "isActive": true,
    "secretPreview": "whsec_************************abc12345"
  }
}
```

> **Note:** The full secret is only shown when first creating the webhook or after regenerating. Subsequent reads show a masked preview.

#### Error Responses

| Status | Error                 | Description                |
| ------ | --------------------- | -------------------------- |
| 401    | Unauthorized          | Missing or invalid API key |
| 404    | No webhook configured | No webhook has been set up |

***

### Create / Update Webhook

Set up or update your vault webhook endpoint. The webhook URL must use HTTPS.

```
PUT /vault/v1/config/webhooks
```

#### Request Body

| Field      | Type      | Required | Description                            |
| ---------- | --------- | -------- | -------------------------------------- |
| `url`      | string    | Yes      | Webhook URL (must be HTTPS)            |
| `events`   | string\[] | No       | Events to subscribe to (default: all)  |
| `isActive` | boolean   | No       | Enable/disable webhook (default: true) |

Available events: `deposit.completed`, `deposit.failed`, `deposit.detected`, `deposit.processing`

#### Example Request

```bash
curl -X PUT https://app.makapay.io/api/vault/v1/config/webhooks \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yoursite.com/webhook/vault",
    "events": ["deposit.completed", "deposit.failed"],
    "isActive": true
  }'
```

#### Response (first time — includes secret)

```json
{
  "success": true,
  "data": {
    "url": "https://yoursite.com/webhook/vault",
    "events": ["deposit.completed", "deposit.failed"],
    "isActive": true,
    "secret": "whsec_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
  }
}
```

#### Response (update — secret is masked)

```json
{
  "success": true,
  "data": {
    "url": "https://yoursite.com/webhook/vault",
    "events": ["deposit.completed", "deposit.failed"],
    "isActive": true,
    "secretPreview": "whsec_************************abc12345"
  }
}
```

> **Important:** Save the `secret` from the first response — it is only shown once. Use it to verify webhook signatures.

#### Error Responses

| Status | Error                      | Description                      |
| ------ | -------------------------- | -------------------------------- |
| 400    | Webhook URL must use HTTPS | URL protocol is not HTTPS        |
| 400    | Invalid webhook URL        | URL format is invalid            |
| 401    | Unauthorized               | Missing or invalid API key       |
| 404    | Vault not configured       | No vault exists for this API key |

***

### Delete Webhook

Remove the webhook configuration entirely.

```
DELETE /vault/v1/config/webhooks
```

#### Example Request

```bash
curl -X DELETE https://app.makapay.io/api/vault/v1/config/webhooks \
  -H "x-api-key: YOUR_API_KEY"
```

#### Response

```json
{
  "success": true,
  "data": null
}
```

#### Error Responses

| Status | Error                 | Description                 |
| ------ | --------------------- | --------------------------- |
| 401    | Unauthorized          | Missing or invalid API key  |
| 404    | No webhook configured | No webhook exists to delete |

***

### Regenerate Webhook Secret

Generate a new HMAC secret for webhook signature verification. The old secret immediately stops working.

> **Warning:** If you regenerate the secret while webhook deliveries are in the retry queue, those retries will use the **new** secret. Ensure your server is updated to verify with the new secret before triggering a regeneration, or briefly pause the webhook (`isActive: false`) while rotating.

```
POST /vault/v1/config/webhooks
```

#### Request Body

```json
{
  "action": "regenerate-secret"
}
```

#### Example Request

```bash
curl -X POST https://app.makapay.io/api/vault/v1/config/webhooks \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"action": "regenerate-secret"}'
```

#### Response

```json
{
  "success": true,
  "data": {
    "secret": "whsec_x9y8z7w6v5u4t3s2r1q0p9o8n7m6l5k4"
  }
}
```

> **Important:** Save this new secret immediately. The old secret is permanently invalidated. Update your webhook handler with the new secret.

#### Error Responses

| Status | Error                 | Description                 |
| ------ | --------------------- | --------------------------- |
| 401    | Unauthorized          | Missing or invalid API key  |
| 404    | No webhook configured | Must create a webhook first |

***

## Payment Webhook Configuration API

Manage payment webhook settings programmatically via API key. This mirrors the Vault Webhook API but for standard payment notifications.

### `GET /api/v1/webhooks`

Get the current webhook configuration.

**Headers:**

| Header      | Required | Description          |
| ----------- | -------- | -------------------- |
| `x-api-key` | Yes      | Your MakaPay API key |

**Response:**

```json
{
  "success": true,
  "error": null,
  "data": {
    "webhookUrl": "https://example.com/webhook",
    "events": ["payment.completed", "payment.withdrawn"],
    "isActive": true,
    "secretPreview": "whsec_************************abcd1234",
    "createdAt": 1709550000000,
    "updatedAt": 1709550000000
  }
}
```

**curl example:**

```bash
curl -X GET https://app.makapay.io/api/v1/webhooks \
  -H "x-api-key: mk_your_api_key"
```

***

### `PUT /api/v1/webhooks`

Create or update webhook configuration. On first creation, a dedicated webhook secret (`whsec_...`) is generated and returned.

**Headers:**

| Header         | Required | Description          |
| -------------- | -------- | -------------------- |
| `x-api-key`    | Yes      | Your MakaPay API key |
| `Content-Type` | Yes      | `application/json`   |

**Request Body:**

| Field      | Type      | Required | Description                                                                   |
| ---------- | --------- | -------- | ----------------------------------------------------------------------------- |
| `url`      | string    | Yes      | Webhook URL (must be HTTPS)                                                   |
| `events`   | string\[] | No       | Events to subscribe to. Default: `["payment.completed", "payment.withdrawn"]` |
| `isActive` | boolean   | No       | Whether the webhook is active. Default: `true`                                |

**Valid events:**

* `payment.completed` — Payment confirmed and funds received
* `payment.withdrawn` — Funds withdrawn to merchant wallet
* `payment.awaiting_gas` — Payment needs gas tank top-up
* `payment.failed` — Payment failed
* `payment.expired` — Payment expired before completion

**Response (creation — includes full secret):**

```json
{
  "success": true,
  "error": null,
  "data": {
    "webhookUrl": "https://example.com/webhook",
    "events": ["payment.completed", "payment.withdrawn"],
    "isActive": true,
    "secret": "whsec_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
  }
}
```

**Response (update — secret is masked):**

```json
{
  "success": true,
  "error": null,
  "data": {
    "webhookUrl": "https://example.com/webhook-v2",
    "events": ["payment.completed"],
    "isActive": true,
    "secretPreview": "whsec_************************abcd1234"
  }
}
```

**curl example:**

```bash
curl -X PUT https://app.makapay.io/api/v1/webhooks \
  -H "x-api-key: mk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/webhook",
    "events": ["payment.completed", "payment.withdrawn"],
    "isActive": true
  }'
```

***

### `DELETE /api/v1/webhooks`

Remove the webhook configuration entirely.

**Headers:**

| Header      | Required | Description          |
| ----------- | -------- | -------------------- |
| `x-api-key` | Yes      | Your MakaPay API key |

**Response:**

```json
{
  "success": true,
  "error": null,
  "data": { "deleted": true }
}
```

**curl example:**

```bash
curl -X DELETE https://app.makapay.io/api/v1/webhooks \
  -H "x-api-key: mk_your_api_key"
```

***

### `POST /api/v1/webhooks`

Regenerate the webhook signing secret. The old secret is immediately invalidated.

> **Warning:** If you regenerate the secret while webhook deliveries are in the retry queue, those retries will use the **new** secret. Ensure your server is updated to verify with the new secret before triggering a regeneration, or briefly pause the webhook (`isActive: false`) while rotating.

**Headers:**

| Header         | Required | Description          |
| -------------- | -------- | -------------------- |
| `x-api-key`    | Yes      | Your MakaPay API key |
| `Content-Type` | Yes      | `application/json`   |

**Request Body:**

```json
{
  "action": "regenerate-secret"
}
```

**Response:**

```json
{
  "success": true,
  "error": null,
  "data": {
    "secret": "whsec_new_secret_value_here_32chars"
  }
}
```

**curl example:**

```bash
curl -X POST https://app.makapay.io/api/v1/webhooks \
  -H "x-api-key: mk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"action": "regenerate-secret"}'
```

***

## SDK (Coming Soon)

Official SDKs for popular languages:

* **JavaScript/TypeScript**: `npm install @makapay/sdk`
* **Python**: `pip install makapay`
* **PHP**: `composer require makapay/sdk`
* **Go**: `go get github.com/makapay/go-sdk`

***

## Changelog

### v1.3.0 (Current)

* Added Payment Webhook Configuration API — manage payment webhooks via API key
* Dedicated webhook secrets (`whsec_...`) for payment webhooks (separate from API key)
* Event filtering — subscribe only to the payment events you care about
* Backward compatible — existing webhooks without secrets continue working

### v1.2.0

* Added Vault Configuration API — setup, update, and manage vault accounts via API
* Added token management endpoints (add/remove accepted tokens)
* Added webhook management endpoints (create/update/delete/regenerate secret)
* Webhook secrets now use cryptographically secure generation (nanoid)
* Webhook URLs must use HTTPS
* Webhook secrets are masked in read responses (full secret only on create/regenerate)
* Added Arbitrum One (Chain ID: 42161) to supported networks

### v1.1.0

* Added public `GET /tokens/price` endpoint (Alchemy + TrustedOracle waterfall)
* Added public `GET /tokens/metadata` endpoint (token name, symbol, decimals, logo)
* Added public `GET /oracle/price` endpoint (direct TrustedOracle lookup)
* Added native token support (ETH, BNB, MATIC) as selectable payment tokens
* Added Base network (Chain ID: 8453) to supported networks table
* Updated supported tokens tables with native tokens and token types

### v1.0.0

* Initial API release
* Payment creation endpoint
* Balance endpoint
* Webhook support


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.makapay.io/developers/api-reference.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
