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

# How to Pass the Signature in Requests

> How to structure signed JSON request envelopes, configure HTTP headers, pass dynamic endpoint parameters, and avoid 403 verification errors.

## Overview

Once you have generated your signature, either locally via [the SHA-256 algorithm](/authentication/signature-generation#method-1-in-code) or using the [Niobi Signature Generation API](/authentication/signature-generation#method-2-signature-api), the final step is formatting and dispatching the HTTP request. Every Niobi API request follows a standardized **envelope structure** that bundles your authentication metadata with your specific payment parameters.

<Note>
  **Pre-requisite: IP Whitelisting**\
  Before sending any API requests to Niobi servers or endpoints (in Sandbox or Production), your server's outgoing public IP address must be whitelisted in the Niobi Dashboard under **Workspace -> IP Whitelisting**. Requests sent from non-whitelisted IPs will be blocked. See our [IP Whitelisting Guide](/ip-whitelisting) for setup steps.
</Note>

***

## Request Envelope Structure

Every signed request to Niobi contains two tiers:

1. **Root-Level Authentication Metadata**: Identifies your integration, timestamp, salt, and cryptographic signature.
2. **Nested `params` Object**: Contains **whatever specific parameters are required by the destination endpoint** you are invoking.

```json theme={null}
{
  "client_id": "YOUR_CLIENT_ID",
  "sender": "YOUR_INTEGRATION_NAME",
  "timestamp": 1724835600,
  "salt": "random_salt_string",
  "signature": "c6b98e1f5d6a7890bc4e123456789abcdef0123456789abcdef0123456789abc",
  "params": {
    /* Destination endpoint-specific parameters go here */
  }
}
```

### Root Fields Specification

| Field       | Type                 | Required | Description                                                                                                               |
| :---------- | :------------------- | :------- | :------------------------------------------------------------------------------------------------------------------------ |
| `client_id` | `string`             | **Yes**  | The unique identifier assigned to your integration in the Niobi Dashboard.                                                |
| `sender`    | `string`             | **Yes**  | The exact name of your integration entity as created in the dashboard.                                                    |
| `timestamp` | `integer` / `string` | **Yes**  | The exact UNIX timestamp (in seconds) used when the request was signed.                                                   |
| `salt`      | `string`             | **Yes**  | A unique random string generated on your server providing an additional layer of security and entropy.                    |
| `signature` | `string`             | **Yes**  | 64-character hexadecimal SHA-256 hash computed using your Secret Key (or returned by the Niobi Signature Generation API). |
| `params`    | `object`             | **Yes**  | The nested parameters required by the specific target endpoint.                                                           |

<Info>
  **The `params` Object is Dynamic:**\
  The outer fields (`client_id`, `sender`, `timestamp`, `salt`, `signature`) never change between endpoints. But the contents of `"params": { ... }` change to match the schema of the endpoint you are calling.
</Info>

***

## Complete Request Examples Across Endpoints

<Tabs>
  <Tab title="Collections / Deposits">
    **Endpoint:** `POST /api/v4/niobi-unified-collections`

    ```json theme={null}
    {
      "client_id": "client_id",
      "sender": "Integration_name",
      "timestamp": 1724835600,
      "salt": "salt_value",
      "signature": "c6b98e1f5d6a7890bc4e123456789abcdef0123456789abcdef0123456789abc",
      "params": {
        "amount": 10000,
        "currency": "KES",
        "country_id": 1,
        "mobile": "254161166649",
        "payment_method_type": "send money",
        "callback_url": "https://yourdomain.com/callbacks",
        "third_party_reference_1": "TX-COLL-001",
        "third_party_reference_2": "CUST-450"
      }
    }
    ```

    [View Unified Collections API Reference ->](/api-reference/collections/unified-collections)
  </Tab>

  <Tab title="Payouts / Disbursements">
    **Endpoint:** `POST /api/v4/niobi-unified-payments`

    ```json theme={null}
    {
      "client_id": "YOUR_CLIENT_ID",
      "sender": "YOUR_INTEGRATION_NAME",
      "timestamp": 1724835600,
      "salt": "random_salt_67890",
      "signature": "e5f6a7b8c90123456789abcdef0123456789abcdef0123456789abcdef012345",
      "params": {
        "amount": 5000,
        "currency": "KES",
        "country_id": 1,
        "payment_method_type": "send money",
        "payment_reference": "PAYOUT-REF-1001",
        "first_name": "Jane",
        "last_name": "Doe",
        "mobile": "254647647649",
        "email": "jane.doe@example.com",
        "city": "Nairobi",
        "postal_code": "00100",
        "address": "Kilimani, Nairobi",
        "client_callback_url": "https://yourdomain.com/payout-callbacks",
        "third_party_reference_1": "PAYOUT-REF-1001",
        "third_party_reference_2": "BATCH-AUG",
        "sendmoney": [
          { "phone_number": "254647647649" }
        ],
        "sub_merchant_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      }
    }
    ```

    [View Unified Payments API Reference ->](/api-reference/disbursement/unified-disbursement)
  </Tab>
</Tabs>

***

## Sub-Merchant Parameter Placement

If you are operating multiple distinct brands or merchants under one master account:

* Pass the approved sub-merchant UUID in `params.sub_merchant_id`.
* The `sub_merchant_id` field **must be included in the pre-signature object** when generating the signature (either in code or via the Niobi Signature Generation API) so that the hash remains valid.
* For more information on creating and managing sub-merchants, see [Sub-Merchant Management](/submerchant/sub-merchant-management).

***

## Common Pitfalls & How to Avoid Them

<AccordionGroup>
  <Accordion title="1. Leaving senderKey in the request body">
    **Error:** Security hazard and potential rejection.\
    **Fix:** The `senderKey` is strictly used on your server to compute the SHA-256 hash. Always delete `senderKey` before sending the payload over the wire.
  </Accordion>

  <Accordion title="2. Modifying params after computing the signature (403 Error)">
    **Error:** `403 - Request was not verified`.\
    **Fix:** If any field in `params` or the root envelope changes (e.g. updating an amount or reference), the signature must be recomputed.
  </Accordion>

  <Accordion title="3. URL-encoding the callback URL before hashing">
    **Error:** Signature mismatch on the server.\
    **Fix:** When stringifying the pre-signature object, ensure `callback_url` remains unencoded (e.g. `https://yourdomain.com/callback` rather than `https%3A%2F%2F...`).
  </Accordion>

  <Accordion title="4. Type mismatch between signing and dispatching">
    **Error:** Signature mismatch.\
    **Fix:** Ensure parameter types remain consistent (e.g. if `amount` is a number `10000`, do not send `"10000"` as a string).
  </Accordion>

  <Accordion title="5. Sending requests from an unwhitelisted IP address">
    **Error:** Request blocked or connection refused.\
    **Fix:** Ensure your server's outgoing public IP address is whitelisted in your Niobi Dashboard under **Workspace -> IP Whitelisting**. See our [IP Whitelisting Guide](/ip-whitelisting).
  </Accordion>

  <Accordion title="6. Unintentional leading or trailing whitespace">
    **Error:** `403 - Request was not verified`.\
    **Fix:** Trailing or leading whitespace can occur on your credentials (`client_id`, `sender`, `senderKey`) when copied from the dashboard, as well as on string parameter values inside `params` (e.g. `callback_url`, `mobile`, `email`, `payment_reference`). Always trim string values across all fields before computing the hash to prevent signature mismatches.
  </Accordion>
</AccordionGroup>

***

## Next Steps

You are now ready to make authenticated API requests:

<div className="next-steps-flow">
  <a href="/collecting-payments/basics" className="next-step-card">
    <div className="next-step-badge">Payin</div>
    <h3>Collecting Payments</h3>
    <p>Learn how to initiate collections across mobile money, cards, and bank transfers.</p>
  </a>

  <div className="next-step-arrow">
    <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
      <path d="M5 12h14M12 5l7 7-7 7" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  </div>

  <a href="/making-payments/basics" className="next-step-card">
    <div className="next-step-badge">Payout</div>
    <h3>Making Payments</h3>
    <p>Learn how to initiate disbursements and payouts across 17+ African markets.</p>
  </a>
</div>
