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

> ## Agent Instructions
> Money is always a decimal string at the currency's precision (for example "29.00"), paired with an ISO 4217 currency field. Never use minor units.
> Build against the sandbox first: base URL https://sandbox-api.bachs.io with sk_sandbox_ keys. Production is https://api.bachs.io with sk_live_ keys; going live is a key swap.
> Treat webhooks (for example collection.succeeded) as the source of truth for fulfilment, never client-side events or redirects.
> Subscriptions are created by completing a checkout for a recurring product. There is no direct create-subscription endpoint.
> IDs carry resource prefixes (cust_, prod_, sub_, chk_, inv_, ref_) and timestamps are ISO 8601 UTC.

# Update Destination

> Rename a destination, make it the one a payout schedule uses, or restate where money lands. The routing fields you send decide which.

## Overview

`PATCH /v1/payouts/destinations/{destination_id}` is the one update this API has. What it does depends on what you send:

* Send only `name` and/or `is_default` and nothing changes about where money lands. This is the safe edit: it never touches review status.
* Send any routing detail (`currency`, `type`, or an account, wallet, or phone field) and the destination is restated in full, the same shape as [Create Destination](/guides/payouts/create-destination). Fields you omit fall back to what is already stored, so you only need to send what's changing.

Setting `is_default` promotes one of your own already-`approved` destinations and demotes whichever one held the flag for that currency; `false` clears it, which leaves a [payout schedule](/guides/payouts/payout-schedules) with nowhere to send that currency and so skips it. Deleting a destination clears the flag too, because an inactive destination cannot receive a scheduled payout.

Why a rename alone cannot move money: a destination's approval is granted for a specific account or wallet. If you could quietly swap the account number on an already-`approved` destination without review, the destination would keep an approval that was never actually granted for its new destination. That is why a routing change always resets `status`, even through this endpoint.

***

## Authentication

**Type:** API Key (required)

| Header | Required | Description |
| - | - | - |
| `Authorization` | Yes | Format: `Bearer sk_sandbox_...` or `Bearer sk_live_...` |
| `Content-Type` | Yes | Must be `application/json` |

***

## Request

### Method & Path

```http theme={"dark"}
PATCH /v1/payouts/destinations/{destination_id}
```

### Path parameters

<Accordion title="View path parameters">
  <ResponseField name="destination_id" type="string" required>
    The ID of the destination to update.
  </ResponseField>
</Accordion>

### Request examples

<CodeGroup>
  ```bash Rename a destination theme={"dark"}
  curl --request PATCH \
    --url https://sandbox-api.bachs.io/v1/payouts/destinations/pd_7Kq2mNv4XbR9dLc0 \
    --header "Authorization: Bearer sk_sandbox_..." \
    --header "Content-Type: application/json" \
    --data '{
      "name": "Primary vendor account"
    }'
  ```

  ```bash Make it the schedule's default theme={"dark"}
  curl --request PATCH \
    --url https://sandbox-api.bachs.io/v1/payouts/destinations/pd_7Kq2mNv4XbR9dLc0 \
    --header "Authorization: Bearer sk_sandbox_..." \
    --header "Content-Type: application/json" \
    --data '{
      "is_default": true
    }'
  ```

  ```bash Move to a new bank account theme={"dark"}
  curl --request PATCH \
    --url https://sandbox-api.bachs.io/v1/payouts/destinations/pd_7Kq2mNv4XbR9dLc0 \
    --header "Authorization: Bearer sk_sandbox_..." \
    --header "Content-Type: application/json" \
    --data '{
      "account_number": "0987654321",
      "bank_code": "058"
    }'
  ```

  ```json Response theme={"dark"}
  {
    "id": "pd_7Kq2mNv4XbR9dLc0",
    "name": "Primary vendor account",
    "type": "bank_account",
    "currency": "NGN",
    "status": "approved",
    "status_reason": null,
    "is_usable": true,
    "is_default": false,
    "account_number": "0123456789",
    "account_name": "ACME LTD",
    "bank_code": "033",
    "bank_name": "United Bank for Africa",
    "phone_number": null,
    "mobile_provider": null,
    "wallet_address": null,
    "network": null,
    "reviewed_at": "2026-08-07T14:31:00Z",
    "created_at": "2026-08-07T14:30:00Z",
    "updated_at": "2026-08-07T15:02:00Z"
  }
  ```
</CodeGroup>

### Request fields

<Accordion title="View request fields">
  <ResponseField name="name" type="string">
    The new name for the destination, 1 to 255 characters.
  </ResponseField>

  <ResponseField name="is_default" type="boolean">
    Make this the destination a payout schedule pays out to for its currency. Setting it demotes the previous default; `false` clears it. The destination must be `approved` and active. Ignored if a routing change in the same request sends the destination back for review.
  </ResponseField>

  <ResponseField name="currency" type="string">
    The currency this destination accepts. Only needed when changing it; defaults to the currency already stored.
  </ResponseField>

  <ResponseField name="type" type="string">
    `bank_account`, `mobile_money`, or `crypto_wallet`. `destination_type` is accepted as a legacy alias. Only needed when changing rail; defaults to the type already stored.
  </ResponseField>

  <ResponseField name="account_number" type="string">
    Bank account number. Required, together with `bank_code`, for a bank-rail destination that omits it and has none stored.
  </ResponseField>

  <ResponseField name="account_name" type="string">
    Account holder name. Unlike [Create Destination](/guides/payouts/create-destination#account-name-and-bank-name-are-accepted-but-always-ignored), an update trusts the name it is given rather than resolving it from the bank.
  </ResponseField>

  <ResponseField name="bank_code" type="string">
    Bank code. Required, together with `account_number`, for a bank-rail destination that omits it and has none stored. Get valid codes from [List Banks](/api-reference/reference/list-reference-banks).
  </ResponseField>

  <ResponseField name="bank_name" type="string">
    Bank name.
  </ResponseField>

  <ResponseField name="phone_number" type="string">
    Phone number, for a mobile-money-rail destination.
  </ResponseField>

  <ResponseField name="mobile_provider" type="string">
    Mobile money provider, for a mobile-money-rail destination.
  </ResponseField>

  <ResponseField name="wallet_address" type="string">
    Destination wallet address, for a crypto-rail destination.
  </ResponseField>

  <ResponseField name="network" type="string">
    Blockchain network. Optional for a currency that names its own network (e.g. `USDT_TRC20`).
  </ResponseField>

  <ResponseField name="metadata" type="object">
    Arbitrary key-value data. Merged over what is already stored on the destination; a partial payload never wipes keys you don't mention.
  </ResponseField>

  At least one field is required.
</Accordion>

***

## Response

### 200 - Success

Returns the updated destination in full. See [Create Destination](/guides/payouts/create-destination#response) for the field reference. `name`, `is_default`, and `updated_at` change on a safe edit; a routing change can also change `status`, `status_reason`, `is_usable`, `reviewed_at`, and any of the account/wallet fields you sent.

***

## Error responses

<AccordionGroup>
  <Accordion title="400 · VALIDATION_ERROR">
    **Cause:** No fields were sent, `name` was empty, or the payload is invalid for the resolved destination type.

    **Resolution:** Send at least one field, and use a non-empty `name`.
  </Accordion>

  <Accordion title="400 · BAD_REQUEST">
    **Cause:** A routing change left a required field for the resolved rail missing, for example `account_number` without `bank_code` for a bank-rail destination.

    **Resolution:** Send the pair of fields together, or omit both to leave the stored routing unchanged.
  </Accordion>

  <Accordion title="400 · CURRENCY_NOT_SUPPORTED">
    **Cause:** The requested destination type and currency have no configured payout rail. See the [withdrawal currency and method table](/for-you/supported-currencies#withdrawals). International bank routing details must match the destination's currency and scheme.

    **Resolution:** Use a supported destination type and currency pair.
  </Accordion>

  <Accordion title="400 · PAYOUT_DESTINATION_NOT_APPROVED">
    **Cause:** `is_default` was `true` on a destination that has not cleared review, including one this same request just sent back for review.

    **Resolution:** Wait for the destination to reach `approved`, then retry with only `is_default`.
  </Accordion>

  <Accordion title="400 · PAYOUT_DESTINATION_INACTIVE">
    **Cause:** `is_default` was `true` on a destination that has been deleted.

    **Resolution:** Register the account again with [Create Destination](/guides/payouts/create-destination) and promote the new one.
  </Accordion>

  <Accordion title="401 · UNAUTHORIZED">
    **Cause:** API key is missing, invalid, or revoked.

    **Resolution:** Use a valid API key in the `Authorization` header.
  </Accordion>

  <Accordion title="404 · DESTINATION_NOT_FOUND">
    **Cause:** `destination_id` does not exist, or belongs to another organization.

    **Resolution:** Verify the destination ID and retry. You can still update a destination that has been [deleted](/guides/payouts/delete-destination); it stays not-usable regardless.
  </Accordion>
</AccordionGroup>

***

## Related Pages

* [Payout Schedules](/guides/payouts/payout-schedules)
* [Create Destination](/guides/payouts/create-destination)
* [List Destinations](/guides/payouts/list-destinations)
* [Delete Destination](/guides/payouts/delete-destination)


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