# Endpoints

Everything the App API exposes today.

The App API is how your app reads the merchant's data. Paths below are **relative to the base URL** — `/payments` means `https://api.southbill.com/v1/app/payments`. Version 1 is **read-only**: every endpoint is a `GET`, anything else returns `405 method_not_allowed`. Write scopes exist in the scope reference but are not callable in v1; they are granted case by case after review.

Base URL: `https://api.southbill.com/v1/app` · Auth: `Authorization: Bearer sb_at_live_…` (see [Authentication](/docs/dev/app-api/authentication)).

## Endpoints

| Method | Path | Scope | What it gives you |
| --- | --- | --- | --- |
| GET | `/merchant` | `merchant:read` | Profile of the merchant that installed your app: company, country, VAT number, status. Call once after install to label the connection. |
| GET | `/payments` | `payments:read` | Processed payments, newest first. Live traffic supports `?status=succeeded`. |
| GET | `/payments/{id}` | `payments:read` | One payment. The `{id}` is the `charge_id` in live and the row `id` in sandbox. |
| GET | `/refunds` | `refunds:read` | Sandbox: refund rows. Live: refunded charges with the running `amount_refunded`. |
| GET | `/disputes` | `disputes:read` | Chargebacks including `evidence_due_by` and `past_due`. |
| GET | `/payouts` | `payouts:read` | Bank settlements. Restricted scope — reconciliation tools only. |
| GET | `/balance` | `payouts:read` | Available and pending balance of the merchant. |
| GET | `/products` | `products:read` | The merchant's catalog (no prices in v1). |
| GET | `/products/{id}` | `products:read` | One product. |
| GET | `/invoices` | `invoices:read` | Issued invoices. **Live only** — sandbox returns an empty list. |
| GET | `/invoices/{id}` | `invoices:read` | One invoice. |
| GET | `/subscriptions` | `subscriptions:read` | Recurring agreements with status and period end. |
| GET | `/analytics/summary` | `analytics:read` | Aggregated volume for a window: `?days=30` (1–365). |

Field-by-field descriptions of every response are in [Objects & fields](/docs/dev/app-api/objects).

## Query parameters

| Parameter | Where | Behaviour |
| --- | --- | --- |
| `limit` | all list endpoints | 1–100, default 25. |
| `offset` | all list endpoints | Row offset, default 0. |
| `status` | `/payments` (live) | Exact match, e.g. `?status=succeeded`. |
| `days` | `/analytics/summary` | 1–365, default 30. |

Unknown query parameters are ignored, not rejected. There are no date-range filters in v1 — page by `offset` and stop at the first object older than your cursor.

## Pagination

```bash
curl "https://api.southbill.com/v1/app/payments?limit=50&offset=100" \
  -H "Authorization: Bearer sb_at_live_…"
```

```json
{ "object": "list", "data": [ … ], "has_more": true }
```

Lists are sorted newest first and carry no total count. Iterate until `has_more` is `false`. New objects arrive while you page, so for exports read the first page frequently rather than deep-paging a moving list.

## Test vs live

The token decides the data source: a sandbox token reads your environment's simulated data, a live token reads the merchant's real data. Field names differ between the two — see the table at the top of [Objects & fields](/docs/dev/app-api/objects).

## Amounts and timestamps

Amounts are integer minor units with a lowercase ISO currency: `{ "amount": 2500, "currency": "eur" }` is €25.00. Never use floats. Timestamps are ISO-8601 UTC; `arrival_date`, `issue_date` and `due_date` are dates without a time part.

## Errors

```json
{ "error": { "type": "insufficient_scope", "message": "Missing required scope: payments:read" } }
```

See [Error & status codes](/docs/dev/dev-reference/errors).
