> ## Documentation Index
> Fetch the complete documentation index at: https://docs.withconvexity.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Conventions

> The shared response envelope, pagination styles, data types, and rate limiting used across every Infra API service.

Every Infra service follows the same conventions. Learn them once and they apply
across the core services (Wallet, Tokenization, and Blockchain Events) and the
supporting Auth-Edge, Projects, Payments, Products, and Subscriptions services.

## Base URL

All paths are relative to the API host:

```text theme={null}
https://dev.api.withconvexity.com
```

Blockchain Events, Products, Subscriptions, and Payments business endpoints are mounted under
the `/v1` prefix. Blockchain Events endpoints additionally live under `/v1/indexer`.

## Response envelope

Successful responses are wrapped in a consistent envelope:

```json theme={null}
{
  "status": true,
  "message": "Products retrieved successfully",
  "data": { }
}
```

| Field     | Type                      | Description                                 |
| --------- | ------------------------- | ------------------------------------------- |
| `status`  | `boolean`                 | `true` on success, `false` on error.        |
| `message` | `string`                  | Human-readable summary of the result.       |
| `data`    | `object \| array \| null` | The payload. Shape depends on the endpoint. |

Error responses use the same envelope with `status: false` and no `data` (some
validation errors add an `errors` array). See [Errors](/getting-started/errors).

## Content types

Send `Content-Type: application/json` on requests with a body, and
`Accept: application/json` to receive JSON. All request and response bodies are JSON.

## Pagination

Three pagination styles are used depending on the service. All are documented per
endpoint; this table is the single reference for which service uses which:

| Service                      | Style                        | Request params     |
| ---------------------------- | ---------------------------- | ------------------ |
| Payments, Subscriptions      | Page/pageSize, inline fields | `page`, `pageSize` |
| Products, Blockchain Events  | Page/pageSize, `meta` block  | `page`, `limit`    |
| Wallet (transaction history) | Limit/offset                 | `limit`, `offset`  |

<Tabs>
  <Tab title="Page / pageSize">
    **Page-based** (Payments, Subscriptions, Products, Blockchain Events). Request with
    `page` and `pageSize` (or `limit`) query parameters:

    ```json theme={null}
    {
      "items": [ ],
      "total": 2,
      "page": 1,
      "pageSize": 20
    }
    ```

    Products and Blockchain Events return a `meta` block instead of inline fields:

    ```json theme={null}
    {
      "data": [ ],
      "meta": { "total": 1, "page": 1, "limit": 20, "totalPages": 1 }
    }
    ```
  </Tab>

  <Tab title="Limit / offset">
    **Cursor/offset** (Wallet transaction history). Request with `limit` and
    `offset`:

    ```json theme={null}
    {
      "items": [ ],
      "pagination": {
        "total": 2,
        "limit": 20,
        "offset": 0,
        "hasMore": false,
        "nextOffset": null
      }
    }
    ```
  </Tab>
</Tabs>

<Info>
  **Page-size limits**

  Defaults are `page=1` and `pageSize`/`limit=20`. Maximums vary by service: Payments
  and Subscriptions cap at `100`; Products caps at `200`; Blockchain Events caps at `200`.
</Info>

## Data types & formats

| Type                                                             | Notes                                                                                    |
| ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| Timestamps                                                       | ISO 8601 UTC strings, e.g. `2026-06-17T10:20:08.000Z`.                                   |
| Monetary amounts (fiat)                                          | Integer **major units** unless noted, e.g. `1500` = ₦1,500.                              |
| Token transfer amounts (Wallet, Tokenization requests/responses) | Decimal strings in the token's **major unit**, e.g. `"150.00"` for 150 USDC.             |
| On-chain event amounts (Blockchain Events payloads)              | Strings in the token's **smallest unit**, as decoded from the raw log, e.g. `"1000000"`. |
| USD values                                                       | Decimal strings, e.g. `"15.871500"`.                                                     |
| Identifiers                                                      | UUIDs, Mongo ObjectIds, or integers depending on the resource.                           |
| Addresses                                                        | Hex strings (`0x...`) for EVM; base58 for Solana.                                        |
| Enums                                                            | Uppercase string constants (e.g. `SUCCESS`, `MONTHLY`, `EVM`).                           |

## Terminal status vocabulary

Wallet and Tokenization each run their own on-chain transaction lifecycle, and they
settle with different words for the same underlying concept. This is intentional
per-service vocabulary, not a bug: check the enum for the specific service rather
than assuming one word applies everywhere.

| Service                   | Terminal states       | Documented in                                                                              |
| ------------------------- | --------------------- | ------------------------------------------------------------------------------------------ |
| Wallet transactions       | `COMPLETED`, `FAILED` | [Wallet overview](/api-reference/wallet/overview#the-transaction-object)                   |
| Tokenization transactions | `CONFIRMED`, `FAILED` | [Tokenization overview](/api-reference/tokenization/overview#the-token-transaction-object) |

Both also pass through a `PENDING` state first; see each overview for the full
lifecycle.

## Network identifiers

Wallet, Tokenization, and Blockchain Events each identify chains differently. There
is no unified scheme today, so use the mapping below rather than assuming a value
from one service works in another:

| Service           | Scheme                                                                                              | Example                                   |
| ----------------- | --------------------------------------------------------------------------------------------------- | ----------------------------------------- |
| Wallet            | `chainType` (`EVM` or `SOLANA`) plus a numeric `chainId` for EVM chains                             | `{ "chainType": "EVM", "chainId": 8453 }` |
| Tokenization      | Short chain code in the `chain` field                                                               | `"BASE"`                                  |
| Blockchain Events | Short network code in the `network` field, one of `ATC`, `BSC`, `ETH`, `BASE`, `POL`, `SOL`, `LISK` | `"BASE"`                                  |

Confirmed crosswalk for the chains Wallet currently supports (see
[Get supported chains](/api-reference/wallet/get-supported-chains) for the live,
authoritative list):

| Chain           | Blockchain Events / Tokenization code | Wallet `chainType` + `chainId`                   |
| --------------- | ------------------------------------- | ------------------------------------------------ |
| Base            | `BASE`                                | `EVM`, `8453`                                    |
| BNB Smart Chain | `BSC`                                 | `EVM`, `56`                                      |
| Solana          | `SOL`                                 | `SOLANA`, none (chain is implied by `chainType`) |

<Note>
  Wallet's supported-chains list does not currently confirm coverage for every
  network Blockchain Events and Tokenization expose (`ATC`, `ETH`, `POL`, `LISK`).
  Don't assume a Blockchain Events/Tokenization network code has a corresponding
  Wallet `chainId` until you see it on
  [Get supported chains](/api-reference/wallet/get-supported-chains).
</Note>

## Webhook signatures

Wallet and Blockchain Events both sign webhook deliveries, but with different
schemes. Verify against the correct one for the service you're integrating:

|               | Wallet (transfer/sign outcomes)                      | Blockchain Events (on-chain events)                                                                                  |
| ------------- | ---------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| Header(s)     | `x-wallet-signature`, `x-wallet-timestamp`           | `X-Indexer-Signature`                                                                                                |
| MAC input     | `"<timestamp>.<rawBody>"`                            | Raw request body                                                                                                     |
| Secret source | You supply your own `webhookSecret` in the request   | Server-issued `signingSecret`, returned once on create/rotate                                                        |
| Retries       | 4 attempts (1s / 5s / 15s backoff, 10s timeout each) | Retried on non-2xx or timeout; inspect and replay via delivery logs (no fixed attempt/backoff schedule is published) |

See [Outcome webhook](/api-reference/wallet/overview#outcome-webhook) and
[Blockchain Events webhooks & capabilities](/guides/indexer-webhooks#verifying-webhook-signatures)
for the full verification code for each.

## Idempotency

Value-moving wallet operations require an `Idempotency-Key` request header so a
retried request never executes twice:

| Endpoint                                                                                      | Header                          |
| --------------------------------------------------------------------------------------------- | ------------------------------- |
| [Initiate transfer](/api-reference/wallet/initiate-transfer) (`POST /v1/wallet/transaction/`) | `Idempotency-Key`, **required** |
| [Sign transaction](/api-reference/wallet/sign-transaction) (`POST /v1/wallet/hd/sign`)        | `Idempotency-Key`, **required** |

Generate a unique key per operation (a UUID works well) and send it on the request:

```bash theme={null}
curl -X POST https://dev.api.withconvexity.com/v1/wallet/transaction \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0c1d2e3f-4a5b-6c7d-8e9f-001122334455" \
  -d '{ "fromAddress": 0, "toAddress": "0x...", "amount": "150.00", "chainType": "EVM", "chainId": 8453 }'
```

If a request is retried with the **same** key (after a network timeout, for example),
the server returns the original result instead of submitting a second transfer or
signature. Reuse a key only when retrying the same operation; use a fresh key for each
new one.

<Note>
  Send a unique key (a UUIDv4 works well) per operation. Reuse a key only when
  retrying the **same** request; every new operation must use a fresh key.
</Note>

## Rate limiting

Endpoints are throttled. When you exceed a limit you receive `429 Too Many Requests`:

```json theme={null}
{
  "status": false,
  "message": "Too many requests. Please try again later.",
  "retryAfter": 42
}
```

The `retryAfter` field (seconds) tells you when to retry. Back off and retry after
that interval. The token endpoint is limited to 30 requests/minute/IP.
