# Field reference

Quick lookup for headers and JSON bodies. Values marked required must be present on successful requests.

## Headers — your requests to SwarmByte

| Header | When | Meaning |
| --- | --- | --- |
| `Content-Type` | Any POST with a JSON body (token, collect, disburse) | Must be `application/json`. |
| `Authorization` | All programmatic routes **except** the two OAuth token URLs | `Bearer <access_token>` from the token endpoint whose scope matches the route (collections vs disbursements). |
| `X-Idempotency-Key` | `POST /v1/collect` and `POST /v1/disburse` only | Required. A unique key **you** generate per logical payment operation (string, non-empty, max **200** characters). Re-send the **same** key when retrying after timeouts or transport errors so SwarmByte returns the same transaction instead of creating a duplicate. Use a **new** key for a new payment. Parallel duplicate posts can receive **409** while the first is still running; after completion, the same key usually replays the stored result with **202**. |

## Body — OAuth token (`/v1/oauth/…/token`)

| Field | Required | Meaning |
| --- | --- | --- |
| `grant_type` | Yes | Must be the literal string `client_credentials`. |
| `client_id` | Yes | Your merchant API key from the dashboard (OAuth "client id"). |
| `client_secret` | Yes | Your merchant API secret (treat like a password; store securely). |

## OAuth token response (`200`)

| Field | Meaning |
| --- | --- |
| `access_token` | Opaque Bearer token; use only as `Authorization: Bearer …` until expiry. |
| `token_type` | Always `bearer` (case as returned). |
| `expires_in` | Lifetime of the access token in seconds (refresh before this window ends). |

## Body — `POST /v1/collect`

| Field | Required | Meaning |
| --- | --- | --- |
| `walletAddress` | Yes | Which of your wallets to credit (string identifier, e.g. `main`). |
| `msisdn` | Yes | Mobile number — Ugandan format (payer for collection, payee for disbursement; see [Integration guide](https://docs.swarmbyte.com/integration.md)). |
| `amount` | Yes | Integer UGX; minimum **500**. Upper bound enforced server-side. |
| `reference` | Yes | Your reference for reconciliation (order id, invoice, etc.), stored on the transaction. |
| `webhookUrl` | Yes | Absolute **HTTPS** URL SwarmByte will POST to for this transaction's lifecycle updates. Must be a valid absolute URL; **HTTPS** is required in production. |

## Body — `POST /v1/disburse`

Same fields as collect, plus `pin`. For disbursements, `amount` is the payout to the recipient (fee-on-top from wallet — see [Integration guide](https://docs.swarmbyte.com/integration.md)).

| Field | Required | Meaning |
| --- | --- | --- |
| `pin` | Yes (programmatic) | Your disbursement PIN (digits only, **4–6** characters). Server-side only; never log or expose in clients. |

## Successful collect/disburse response (`202`) — `data` object

| Field | Meaning |
| --- | --- |
| `transactionId` | Primary id for polling and webhooks; store in your system. |
| `walletAddress` | Wallet used for the transaction. |
| `amount` / `fee` / `netAmount` | UGX amounts. **Collections:** `netAmount` is what your wallet is credited after the platform fee. **Disbursements (fee-on-top):** `amount` is what the recipient receives; `fee` is debited from your wallet in addition; `netAmount` equals `amount`. |
| `status` | Current transaction status (e.g. `PENDING` immediately after accept). |
| `provider` | Mobile money provider for the transaction (e.g. `MTN` or `AIRTEL`). |
| `createdAt` | ISO 8601 timestamp. |

## `GET /v1/collect/transactions/:transactionId` — `data` (success shape)

| Field | Meaning |
| --- | --- |
| `transactionId` | Same id as collect response. |
| `type` | Must be `COLLECTION` on this route (otherwise **403**). |
| `status` | Current lifecycle status (see Status values under [Collection status](https://docs.swarmbyte.com/collect-status.md)). |
| `providerRef` | Provider reference when available; may be null early in the flow. |
| `reference` | Your merchant reference from the collect request. |
| `failureReason` | Human-readable detail when failed; often null. |
| `updatedAt` | Last update time. |

Disbursement GET responses mirror this list with `type: DISBURSEMENT` on the disbursement status route.

## Inbound webhooks — headers SwarmByte sends

| Header | Meaning |
| --- | --- |
| `Content-Type` | `application/json` |
| `X-Swarmbyte-Timestamp` | ISO 8601 time when the webhook request was built (for ordering/debugging). |
| `User-Agent` | `SwarmByte-Webhooks/1.0` |

HTTP callbacks from SwarmByte to your `webhookUrl` are **not** signed (no HMAC or shared-secret header). Rely on HTTPS, an unguessable path if possible, and idempotent handling by `transactionId`.

## Inbound webhooks — JSON fields

| Field | Meaning |
| --- | --- |
| `event` | Event name for this delivery (e.g. `collection.initiated`, `collection.success`, `collection.failed`, `disbursement.initiated`, `disbursement.success`, `disbursement.failed`). You may also receive `transaction.updated`. Always key your ledger off `transactionId`, `status`, and `type`. |
| `transactionId` | Same `transactionId` returned by collect/disburse and status GET. |
| `status` | Transaction status at the time of the webhook. |
| `type` | `COLLECTION` or `DISBURSEMENT`. |
| `amount` / `fee` / `netAmount` | UGX values. Collections: `netAmount` is after fee. Disbursements: `amount` is recipient payout; `netAmount` equals `amount` (fee charged on top from wallet). |
| `msisdn` | Counterparty mobile number for the payment. |
| `timestamp` | ISO 8601 time included in the payload. |

Source: https://docs.swarmbyte.com/field-reference
