**Take payments. Keep moving. Grow your way.**

Handle checkout, billing and customer tools through APIs and SDKs for web and
mobile. The Dime Partner API is organised around REST, uses predictable
resource-oriented URLs, accepts JSON request bodies, and returns JSON responses.

**Current version: v2.** All new integrations should use it. [v1](/apis/v1/dime-v1)
remains available and supported, but will be deprecated.

## Base URL

```
https://sandbox.api.dimepay.app/dapi/v2
```

Every production account can enable sandbox mode, so these docs target sandbox
throughout. Swap the host for production once your integration is ready.

## Authentication

Send your client key in the `client_key` header on every request:

```bash
curl https://sandbox.api.dimepay.app/dapi/v2/invoices \
  -H "client_key: ck_your_sandbox_key"
```

Your key carries privileges — keep it out of source control, client-side code,
and anywhere it could be read by a third party.

Requests without a valid key return `401`.

## Identifiers

Every resource carries a prefixed id, so an identifier is recognisable on
sight:

| Prefix | Resource |
|  --- | --- |
| `ord_` | Order |
| `inv_` | Invoice |
| `txn_` | Transaction |
| `lnk_` | Payment link |
| `crq_` | Card request |
| `cus_` | Customer |
| `str_` | Store |


Orders and card requests also carry a shorter public `token`, used in hosted
page URLs. Either form works when retrieving a resource.

An id without its prefix is rejected with `400`, rather than silently
returning nothing.

## Requests and responses

Send plain JSON. Resources come back at the top level, with no wrapper:

```json
{
  "id": "ord_30800d0f-da91-4c38-9ec2-1016c27f8209",
  "object": "order",
  "status": "PENDING",
  "currency": "JMD",
  "total": 1100
}
```

Every resource carries an `object` field naming its type, so a response is
self-describing.

## Errors

Dime uses conventional HTTP status codes: `2xx` for success, `4xx` for a
problem with the request, `5xx` for a problem on our side.

Failures return a single `error` object:

```json
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_missing",
    "message": "Order ID is required.",
    "param": "id"
  }
}
```

`type` is always one of four values:

| Type | Meaning |
|  --- | --- |
| `invalid_request_error` | The request was malformed or a parameter was rejected |
| `card_error` | The card was declined or failed verification |
| `idempotency_error` | An idempotency key was reused with different parameters |
| `api_error` | Something went wrong on Dime's side |


`param` names the offending field where one applies, so an error can be
surfaced against the right input in your UI.

## Pagination

List endpoints are cursor-paginated. They return an envelope:

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

There is no total count. `has_more` tells you whether another page exists.

| Parameter | Description |
|  --- | --- |
| `limit` | How many records to return, 1–100. Defaults to 10. |
| `starting_after` | Return records after this id — walk forward |
| `ending_before` | Return records before this id — walk backward |


To page forward, pass the last id you received as `starting_after`:

```bash
curl "https://sandbox.api.dimepay.app/dapi/v2/invoices?limit=25&starting_after=inv_ae1752f7-36b8-4ab3-bc0b-129eda89cc34" \
  -H "client_key: ck_your_sandbox_key"
```

Supplying both `starting_after` and `ending_before` is rejected.

## Amounts and currencies

Amounts are expressed in the currency's major unit — `1100` in `JMD` is
1,100 Jamaican dollars, not 11.00.

Supported currencies: `USD`, `JMD`, `GBP`, `EUR`, `TTD`, `BBD`, `XCD`, `GYD`,
`SRD`.

Orders enforce a minimum: **200 JMD** or **1 USD**. Other currencies have no
configured minimum.

## Resources

| Resource | Use it to |
|  --- | --- |
| **Orders** | Take a payment through a hosted checkout page |
| **Invoices** | Bill a customer for goods or services |
| **Payment Links** | Share a URL that collects a payment |
| **Card Requests** | Capture and store a customer's card |
| **Payments** | Charge a stored card, then capture, void, or refund |
| **Transactions** | Read the record of money moving |
| **Subscriptions** | Manage recurring billing |


## Moving from v1

If you have an existing v1 integration, three things differ:

**Plain JSON.** v1 signs the request body as a JWT and wraps it in a `data`
field. v2 takes the body directly — sending `data` is rejected.

**No envelope.** v1 returns `{ statusCode, headers, body }` with the payload
nested under `body.response`. v2 returns the resource at the top level.

**One error shape.** v1 returns validation failures as an array of message
strings. v2 returns a single `error` object with a machine-readable `code` and
the offending `param`.