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

# Quickstart

> Place your first order in the sandbox and see the resulting position.

This guide takes you from your API key to a filled order in five requests. The sandbox has the same endpoints as the live API, but it has its own host and keys, uses test money, and doesn't connect to the exchange.

## Before you begin

When we set up your sandbox access, we send you the sandbox host, a sandbox API key, and two account codes: one to trade with, and one ending in `99` that has a zero balance, so you can test a rejected order.

The examples use these placeholders:

| Placeholder   | Replace with                                         |
| ------------- | ---------------------------------------------------- |
| `$KEY`        | Your sandbox API key                                 |
| `$ACCOUNT`    | The account you trade with                           |
| `$ACCOUNT_99` | The account ending in `99`                           |
| `$ORDER_ID`   | The `id` returned when you place the order in step 3 |

Send every request with the `Authorization: Bearer $KEY` header. Request and response bodies are JSON, and all amounts are integers in kobo, so ₦475.00 is `47500`.

## Place your first order

<Steps>
  <Step title="List your accounts">
    Confirm that your key works and see which accounts you can trade for.

    ```http Request theme={"dark"}
    GET /v1/accounts
    Authorization: Bearer $KEY
    ```

    ```http Response theme={"dark"}
    HTTP/1.1 200 OK

    {
      "object": "list",
      "data": [
        {
          "object": "account",
          "code": "$ACCOUNT"
        },
        {
          "object": "account",
          "code": "$ACCOUNT_99"
        }
      ]
    }
    ```
  </Step>

  <Step title="Estimate the cost">
    Get an estimate before you place the order. An estimate doesn't place or store anything.

    ```http Request theme={"dark"}
    POST /v1/orders/estimate
    Authorization: Bearer $KEY
    Content-Type: application/json

    {
      "account": "$ACCOUNT",
      "symbol": "DANGCEM",
      "side": "buy",
      "quantity": 10,
      "type": "market",
      "time_in_force": "day"
    }
    ```

    ```http Response theme={"dark"}
    HTTP/1.1 200 OK

    {
      "object": "order_estimate",
      "account": "$ACCOUNT",
      "symbol": "DANGCEM",
      "side": "buy",
      "quantity": 10,
      "type": "market",
      "time_in_force": "day",
      "price_kobo": null,
      "estimated_total_kobo": 530338
    }
    ```

    A market order is priced at the day's price limit: the upper limit for a buy, the lower limit for a sell. In the sandbox, the limits are 10% either side of the listed price, and charges are a flat 1.5%. This estimate works out as follows:

    |                                                                           | Kobo     |
    | ------------------------------------------------------------------------- | -------- |
    | Upper price limit: ₦475.00 plus 10%                                       | `52250`  |
    | 10 shares at the upper limit: 10 × 52250                                  | `522500` |
    | Plus 1.5% charges: 522500 × 1.015 = 530337.5, rounded to the nearest kobo | `530338` |

    The sandbox then fills the order at ₦475.00, so the account pays `482125` kobo: 10 × 47500, plus 1.5%. A sell estimate is priced at the lower limit and is what you'd receive after charges. In live, the estimate is the broker's figure, and it's indicative.
  </Step>

  <Step title="Place the order">
    <Tip>
      Use a unique `Idempotency-Key` for each order. If a request times out, retry it with the same key and you'll get the original order back instead of a duplicate.
    </Tip>

    ```http Request theme={"dark"}
    POST /v1/orders
    Authorization: Bearer $KEY
    Content-Type: application/json
    Idempotency-Key: my-first-order

    {
      "account": "$ACCOUNT",
      "symbol": "DANGCEM",
      "side": "buy",
      "quantity": 10,
      "type": "market",
      "time_in_force": "day"
    }
    ```

    ```http Response theme={"dark"}
    HTTP/1.1 201 Created

    {
      "object": "order",
      "id": "ord_62jxryztxctob7uopekg",
      "account": "$ACCOUNT",
      "symbol": "DANGCEM",
      "side": "buy",
      "quantity": 10,
      "type": "market",
      "time_in_force": "day",
      "price_kobo": null,
      "state": "pending",
      "exchange_order_id": "100001",
      "filled_quantity": 0,
      "reason": null,
      "reject_reason": null,
      "created_at": "2026-09-25T06:12:34Z",
      "updated_at": "2026-09-25T06:12:34Z"
    }
    ```

    The `pending` state means the order is open at the exchange.
  </Step>

  <Step title="Check the order status">
    The sandbox fills market orders immediately. We check the broker for fills every 30 seconds, so the fill appears within 30 seconds, and we send you an `order.filled` [event](/webhooks). Retrieve the order to see its `filled` state.

    ```http Request theme={"dark"}
    GET /v1/orders/$ORDER_ID
    Authorization: Bearer $KEY
    ```

    ```http Response theme={"dark"}
    HTTP/1.1 200 OK

    {
      "object": "order",
      "id": "ord_62jxryztxctob7uopekg",
      "account": "$ACCOUNT",
      "symbol": "DANGCEM",
      "side": "buy",
      "quantity": 10,
      "type": "market",
      "time_in_force": "day",
      "price_kobo": null,
      "state": "filled",
      "exchange_order_id": "100001",
      "filled_quantity": 10,
      "reason": null,
      "reject_reason": null,
      "created_at": "2026-09-25T06:12:34Z",
      "updated_at": "2026-09-25T06:13:02Z"
    }
    ```
  </Step>

  <Step title="View the position">
    The filled order now appears as a position on the account.

    ```http Request theme={"dark"}
    GET /v1/accounts/$ACCOUNT/positions
    Authorization: Bearer $KEY
    ```

    ```http Response theme={"dark"}
    HTTP/1.1 200 OK

    {
      "object": "list",
      "data": [
        {
          "object": "position",
          "symbol": "DANGCEM",
          "name": "DANGCEM",
          "quantity": 10,
          "average_cost_kobo_decimal": "47500",
          "market_price_kobo": 47500,
          "asset_class": "EQUITY",
          "sector": "",
          "industry": ""
        }
      ],
      "has_more": false,
      "next_cursor": null
    }
    ```
  </Step>
</Steps>

You've completed a full order cycle. Every endpoint is described in the API reference, and every error code is listed in the [error reference](/errors).

## Run this guide in Postman

Import the [Postman collection](/matamba-gateway.postman_collection.json) and the [sandbox environment](/matamba-gateway.sandbox.postman_environment.json), then fill in `base_url`, `api_key`, `account` and `account_99` in the environment. The collection runs these five requests in order, then requests that fail on purpose. It refuses to run with anything but a sandbox key.

To generate a client in your own language, use the [OpenAPI file](/openapi.json).

## How the sandbox behaves

|              |                                                                                                                                                                                                                    |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Symbols      | Four symbols are available: `DANGCEM` at ₦475.00, `MTNN` at ₦250.00, `ZENITHBANK` at ₦38.50, and `STANBICETF30` (an ETF) at ₦120.50.                                                                               |
| Fills        | Market orders fill immediately and in full at the listed price. Limit orders fill immediately if the limit price crosses the listed price. Otherwise they stay open until you cancel them or the trading day ends. |
| Market hours | The sandbox market never closes, so you can test at any time.                                                                                                                                                      |
| Balance      | Every account starts with ₦1,000,000.00, except the account ending in `99`, which starts with ₦0.                                                                                                                  |
| Price limits | 10% either side of the listed price. A market buy is priced at the upper limit and a market sell at the lower limit.                                                                                               |
| Fees         | The sandbox charges a flat 1.5%. Live fees are set by the broker.                                                                                                                                                  |
| Reset        | Restarting the sandbox clears all its data.                                                                                                                                                                        |

## Test your error handling

Before you go live, send these requests to check that your integration handles each error.

| Request                                                   | Response                                                                                                   |
| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| Buy on the account ending in `99`                         | `422 order_rejected` with `reject_reason: insufficient_funds`, because the account has a zero balance.     |
| Place a limit order on `DANGCEM`                          | `422 order_rejected` with `reject_reason: limit_orders_etf_only`. Limit orders are accepted only for ETFs. |
| Place a market order for a symbol that isn't listed above | `422 unknown_symbol`. The order isn't stored, so you can reuse the idempotency key.                        |
| Reuse an `Idempotency-Key` with a different order         | `409 duplicate_order`                                                                                      |
| Exceed your per-second request limit                      | `429 rate_limited` with a `Retry-After: 1` header                                                          |
| Exceed your daily order value limit                       | `422 limit_exceeded`                                                                                       |
