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

# Recipients and destinations overview

> The two objects that answer "where is this money going", how they differ, and why one of them expires.

Before money can move, Sakawave has to know where it is going and be satisfied it can get there. Two objects do that, and confusing them is the most common mistake in this part of the API.

| | **Recipient** | **Destination** |
| - | - | - |
| What it is | Someone you pay, saved | A resolved, verified target |
| Lifetime | Until you delete it | **24 hours**, and single use |
| Reusable | Yes | No |
| Spent by | Nothing | One transfer |
| Required to transfer | No | **Yes** |

A transfer takes a `destinationId`, never a recipient. A recipient is a convenience that saves you re-entering routing details; a destination is the thing a transfer actually spends.

## Recipient

A recipient is provider-neutral identity — *who*, not *how*.

```json theme={null}
{
  "id": "01K2Z3AB4G5H6J7K8MNPQRSTVW",
  "type": "individual",
  "displayName": "Ada Okafor",
  "relationship": "vendor",
  "email": "ada@example.com",
  "phoneNumber": "+2348012345678",
  "address": null,
  "defaultPaymentDetailId": "01K2Z3AB4Q5R6S7T8VWXYZABCD",
  "paymentDetails": [],
  "createdAt": "2026-08-14T09:05:00.000Z"
}
```

`relationship`, `email`, and a full `address` are required at creation — not because Sakawave wants them, but because payout providers ask for them. A recipient missing any of them cannot be turned into a destination, and the refusal comes later as `422 recipient_profile_incomplete`.

## Payment detail

Routing hangs off a recipient as one or more payment details — *how*, for one route.

```json theme={null}
{
  "id": "01K2Z3AB4Q5R6S7T8VWXYZABCD",
  "recipientId": "01K2Z3AB4G5H6J7K8MNPQRSTVW",
  "routeId": "01K2Z3AB4M5N6P7Q8RSTVWXYZA",
  "paymentMethod": "bank-transfer",
  "currency": "KES",
  "country": "KE",
  "accountHolderName": "Ada Okafor",
  "institutionName": "Example Bank",
  "maskedIdentifier": "•••• 6789",
  "isDefault": true,
  "providerLocked": false,
  "createdAt": "2026-08-14T09:06:00.000Z"
}
```

The routing values you send are validated against the route's own field descriptors, **encrypted at rest, and never returned**. `maskedIdentifier` — the last four characters — is all you get back. If you need to show a customer what they entered, keep your own copy.

One recipient can hold several details: a bank account and a mobile-money number, or accounts in two currencies. Exactly one is the default.

## Destination

A destination is the resolved, verified answer, and it is deliberately short-lived.

```json theme={null}
{
  "id": "01K2Z3AB4F5G6H7J8KMNPQRSTV",
  "type": "external",
  "currency": "KES",
  "displayName": "ADA OKAFOR",
  "routeId": "01K2Z3AB4M5N6P7Q8RSTVWXYZA",
  "recipientId": "01K2Z3AB4G5H6J7K8MNPQRSTVW",
  "institutionName": "Example Bank",
  "accountNumberLast4": "6789",
  "expiresAt": "2026-08-15T09:05:00.000Z"
}
```

Creating one is what performs the checks: the currency permits this kind of transfer, the route serves the country, the required fields are present, and — where the route supports it — the account is looked up with the provider and **`displayName` becomes the name the bank holds**, not the name you sent.

<Warning>
  A destination expires after 24 hours and is consumed by the transfer that spends it. Both cases return `409 transfer_destination_expired`, so an unused destination and a reused one look identical. Create one per intended payment, immediately before the transfer.
</Warning>

## Two ways in

```mermaid theme={null}
flowchart TD
    A["POST /v1/transfer-destinations<br/>inline: own account · tag · external"] --> D["Destination<br/>24h · single use"]
    R["POST /v1/transfer-recipients<br/>who you are paying"] --> PD["POST …/payment-details<br/>how to reach them"]
    PD --> B["POST /v1/transfer-destinations/<br/>recipients/{recipientId}"]
    B --> D
    D --> T["POST /v1/transfers<br/>destinationId"]
```

**Inline** suits a one-off payout: everything in one call, nothing kept. **Saved** suits anyone you pay repeatedly: the routing fields are entered once and re-verified for you each time.

Both produce the same object, and a transfer cannot tell them apart.

## What is stored, and what is not

| Value | Stored | Returned |
| - | - | - |
| Account number, IBAN, phone number | Encrypted | Last four only, as `maskedIdentifier` |
| Institution name | Yes | Yes |
| Verified account name | Yes | Yes, as `displayName` |
| Which provider settles the route | Yes | **No** |

## Next

<CardGroup cols={2}>
  <Card title="Introduction" icon="book-open" href="/services/recipients/introduction">
    Inline or saved, and how to choose.
  </Card>

  <Card title="Get started" icon="play" href="/services/recipients/get-started">
    A recipient, a payment detail, and a destination.
  </Card>

  <Card title="Setup and configuration" icon="sliders" href="/services/recipients/setup-and-configuration">
    Limits, storage, and the 24-hour window.
  </Card>

  <Card title="Routing fields and verification" icon="route" href="/services/recipients/routing-fields-and-verification">
    Building payloads from field descriptors.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.