# Exchange & Dynamic API (/docs/products/ussd-flows/developers/exchange-api/overview)

Two things in a flow can call your server: an **exchange action** and a **dynamic page**. Both send an encrypted HTTP POST to a URL you set, wait for your reply, and then carry on based on it. An exchange runs after a page is done. A dynamic page has no content of its own: your server decides what happens there.

> **Info:** Requests and replies are encrypted. Add an RSA public key to the flow before you publish it. See [Encryption Model](/docs/products/ussd-flows/developers/security/overview).

## Exchange or dynamic page

|               | Exchange                                                     | Dynamic page                                 |
| ------------- | ------------------------------------------------------------ | -------------------------------------------- |
| **Runs**      | After a page is done (`on_done.action: "exchange"`)          | When the subscriber reaches a `dynamic` page |
| **Use it to** | Process what the subscriber entered, then pick the next step | Let your server decide the whole step        |

Both send the same request and expect the same reply: `navigate` or `stop`.

## Exchange actions

An exchange runs when a page with `on_done.action: "exchange"` is done. Monime sends everything collected so far to your URL and waits up to 10 seconds for a reply.

```json
{
  "id": "confirm",
  "component": {
    "type": "prompt",
    "label": "Send SLE $(page.enter_amount.value) to $(page.enter_recipient.value)?",
    "data_type": "boolean"
  },
  "on_done": {
    "action": "exchange",
    "url": "https://api.kabalafarms.sl/ussd/confirm-transfer",
    "dataExport": {
      "phone_number": "$(rc.player_msisdn)"
    }
  }
}
```

Use an exchange to:

- Check input against your business rules before the subscriber moves on
- Look up account details, fees or limits to show on the next page
- Save what the subscriber entered so far
- Send the subscriber to a different page based on your own logic

## Dynamic pages

A dynamic page calls your server as soon as the subscriber reaches it. Your reply decides what happens next.

```json
{
  "id": "account_menu",
  "component": {
    "type": "dynamic",
    "url": "https://api.kabalafarms.sl/ussd/account-menu"
  }
}
```

Use a dynamic page to:

- Build a menu from live data, such as the subscriber's own accounts
- Apply logic too complex for the flow JSON

A dynamic page can also have `on_done.dataExport`. It works the same as on an exchange.

## Request

Monime sends a POST with `Content-Type: application/json`. The body holds two encrypted fields, `encryptedAesKey` and `encryptedExchangeData`. [Decrypting & Responding](/docs/products/ussd-flows/developers/security/implement) shows how to read them.

Requests sent while you test in the Simulator also carry the header `Is-Simulation: true`.

After decryption, the payload looks like this:

```json
{
  "global": {
    "sessionId": "5f0c1e8a-2b7d-4c1e-9a43-7d2f8e6b1c90",
    "networkName": "Orange",
    "subscriberId": "c9b4e86f-a1d8-5056-8dc4-5d1aafc6994a",
    "subscriberMsisdn": "+23276****56",
    "networkProviderName": "Orange Money"
  },
  "currentPage": "confirm",
  "flowData": {
    "main_menu": "1",
    "enter_recipient": "ACC12345678",
    "enter_amount": "500",
    "confirm": "true"
  },
  "exportedData": {
    "phone_number": "+23276123456"
  }
}
```

| Field                        | Type   | Description                                                                                                                                                |
| ---------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `global.sessionId`           | string | ID of the USSD session. The same for every call in one session.                                                                                            |
| `global.networkName`         | string | Mobile network, for example `"Orange"` or `"Africell"`                                                                                                     |
| `global.subscriberId`        | string | Stable ID for the subscriber's phone number. See [Subscriber Identification](/docs/products/ussd-flows/developers/exchange-api/subscriber-identification). |
| `global.subscriberMsisdn`    | string | The subscriber's phone number with four digits hidden. For display only.                                                                                   |
| `global.networkProviderName` | string | Mobile money provider, for example `"Orange Money"` or `"Afrimoney"`. Can be missing.                                                                      |
| `currentPage`                | string | ID of the page that made this call                                                                                                                         |
| `flowData`                   | object | Everything the subscriber has entered so far, keyed by page ID. Values are always strings.                                                                 |
| `exportedData`               | object | Values you chose in `on_done.dataExport`. Left out when there are none.                                                                                    |

`exportedData` is for values that `flowData` doesn't hold, such as `rc.*`, `sc.*` or `session.*` values. Each value must be a string, number or boolean. Nested objects and arrays aren't allowed.

Your server must reply with HTTP 200 within 10 seconds. [Response Format](/docs/products/ussd-flows/developers/exchange-api/response) describes the reply and what happens when a call fails.
