# Data models

Every object the API returns, with field names, types and notes. Conventions used throughout:

| Convention | Description |
| --- | --- |
| Amounts | Integer **minor units** with an ISO-4217 `currency` (9700 with `USD` = $97.00). Amounts never mix currencies in one operation |
| Ids | Opaque UUID strings — treat them as case-sensitive and stable |
| Timestamps | RFC 3339 UTC strings (`2026-10-08T09:12:00Z`) |
| Pagination | `limit` + `cursor` request fields; responses carry `next_cursor` (null when there is no next page) |
| Errors | `{"error": "reason"}` with the HTTP status carrying the class — see [Errors & idempotency](/errors) |

## Organization

Returned by `GET /orgs`, `GET /orgs/{id}` and org creation.

| Field | Type | Notes |
| --- | --- | --- |
| `org_id` | string | Organization id |
| `name` | string | Business name |
| `country_code` | string | ISO-3166 alpha-2; sets the default currency and payout rails |
| `status` | string | `ACTIVE` for a usable organization |
| `role` | string | The caller's role in this org (`GET /orgs` only) |

## Member

Returned by `GET /orgs/{id}/members`.

| Field | Type | Notes |
| --- | --- | --- |
| `user_id` | string | User id |
| `email` | string | Sign-in email |
| `first_name`, `last_name` | string | Display name |
| `role` | string | `owner`, `admin`, `finance`, `support` or `developer` |
| `status` | string | `ACTIVE` once the user has joined |

## Invite

Returned by `GET /orgs/{id}/invites`.

| Field | Type | Notes |
| --- | --- | --- |
| `invite_id` | string | Invite id, used to revoke |
| `email` | string | Invited address |
| `role` | string | Role granted on join |
| `status` | string | `PENDING` until claimed or revoked |

## API key

Created by `POST /apikeys` (raw key returned once), listed by `GET /orgs/{id}/keys`.

| Field | Type | Notes |
| --- | --- | --- |
| `key` | string | The raw key (`fl_test_…` / `fl_live_…`) — **create response only**, shown once |
| `id` / `key_id` | string | Key id, used to revoke |
| `prefix` | string | First characters of the key, safe to display |
| `name` | string | Label you gave the key |
| `env` | string | `sandbox` or `live` |
| `status` | string | `ACTIVE` or revoked |

## Terminal

Returned by `GET /terminals` and terminal creation.

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string | Terminal id |
| `title` | string | Display name |
| `terminal_type` | string | `REUSABLE` (permanent terminal id — present as QR, NFC or link) or `USE_ONCE` (auto-created per checkout) |
| `status` | string | `ACTIVE` or `INACTIVE` |
| `created_at` | timestamp | Creation time |

## Checkout item

One line in a checkout or sale.

| Field | Type | Notes |
| --- | --- | --- |
| `product_id` | string | Your SKU or product id |
| `display_name` | string | Human-readable name |
| `unit_price` | amount | Price per unit in minor units |
| `qty` | integer | Quantity, greater than 0 |
| `cashback_rate` | integer | Cashback in basis points (500 = 5%, max 10000) |
| `item_image_url` | string | Optional image shown to the shopper |
| `item_url` | string | Optional product link shown to the shopper |

## Checkout

Returned by checkout creation (`{id, terminal_id}`), by `GET /terminals/{id}/checkout` and inside sale details.

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string | Checkout id — the value used for authorize and capture |
| `terminal_id` | string | Terminal this checkout belongs to |
| `merchant_id` | string | Your organization id |
| `items` | array | [Checkout items](#checkout-item) |
| `currency` | string | ISO-4217 |
| `shipping_amount`, `tax_amount` | amount | As sent at creation |
| `total` | amount | `sum(unit_price x qty) + shipping_amount + tax_amount` |
| `total_cashback` | amount | The cashback pot for this cart (see [Cashback](/cashback)) |
| `order_id` | string | Your reference, echoed back |
| `status` | string | `PENDING`, `AUTHORIZED`, `CAPTURED`, `VOIDED`, `EXPIRED` or `SUPERSEDED` |
| `expires_at` | timestamp | When an unpaid checkout stops being payable |
| `created_at` | timestamp | Creation time |

## Sale

List rows come from `GET /orgs/{id}/sales`; `GET /sales/{id}` adds the cart and authorization.

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string | Checkout id |
| `terminal_id`, `terminal_title` | string | Where the sale was made |
| `total_minor` | amount | Gross amount |
| `currency` | string | ISO-4217 |
| `cashback_minor` | amount | Cashback pot funded by this sale |
| `status` | string | Checkout status (see above) |
| `created_at` | timestamp | Creation time |
| `auth` | object | Detail only: `{id, status}` of the charge authorization |
| `items` | array | Detail only: [Checkout items](#checkout-item) |

## Charge capture result

Returned by `POST /charges/{id}/capture`.

| Field | Type | Notes |
| --- | --- | --- |
| `journal_id` | string | Transaction reference for this capture — stable across retries |
| `mdr_fee` | amount | Your processing fee for this charge |
| `recommender_amount` | amount | Cashback earned by the recommender (0 when the purchase did not come from a recommendation) |
| `buyer_amount` | amount | Always 0 at capture — the buyer's share is deferred |
| `deferred_buyer_amount` | amount | Cashback the buyer earns by recommending what they bought |
| `recommender_id` | string | Primary recommender's user id, when present |
| `recommenders` | array | One entry per recommender: `{user_id, amount}` |

## Return result

Returned by `POST /charges/{id}/return`.

| Field | Type | Notes |
| --- | --- | --- |
| `return_id` | string | Refund reference |
| `refund` | amount | Principal returned to the shopper (goods + pro-rata shipping and tax) |
| `buyer_cut` | amount | Pending buyer cashback removed by this return |
| `rec_cut` | amount | Pending recommender cashback removed by this return |
| `award_adjusted` | boolean | True when pending cashback was reduced or voided |

## Cashback summary

Returned by `GET /orgs/{id}/cashback/summary` — one entry per currency.

| Field | Type | Notes |
| --- | --- | --- |
| `currency` | string | ISO-4217 |
| `captured_count` | integer | Number of captured charges |
| `captured_minor` | amount | Gross volume captured |
| `funded_minor` | amount | Cashback funded by you |
| `social_count` | integer | Captures that came from a recommendation |
| `to_buyers_minor` | amount | Cashback earned by buyers |
| `to_recommenders_minor` | amount | Cashback earned by recommenders |

## Webhook payload

Every delivery carries the event name, a unique delivery id and an HMAC signature in headers (see [Webhooks](/webhooks)). The JSON body depends on the event:

| Event | Body fields |
| --- | --- |
| `checkout.authorized` | `checkout_id`, `auth_id`, `total_minor`, `currency`, `consumer_id` |
| `charge.captured` | `checkout_id`, `auth_id`, `mdr_fee`, `buyer_amount`, `deferred_buyer_amount`, `recommender_amount` |
| `charge.voided` | `auth_id` |
| `charge.returned` | `auth_id`, `return_id`, `refund`, `buyer_cut`, `rec_cut`, `award_adjusted` |

## Payout

Created by `POST /payouts` (returns `instruction_id`); listed by `GET /payouts`.

| Field | Type | Notes |
| --- | --- | --- |
| `instruction_id` / `id` | string | Payout reference |
| `provider` | string | Banking partner handling the transfer |
| `amount_minor` | amount | Amount sent |
| `currency` | string | ISO-4217 |
| `status` | string | `PENDING` while the banking partner processes, then settled |
