# Link a Wallet to the Customer

> Coming soon, upon request — this feature is turned on for your tenant by the Aurea team. [Contact us](https://www.aureahub.com/contact)

Link one of the user's Aurea wallets to their bank ramp customer on a chain, so the bank ramp pays to it and takes from it.

## Overview

The bank ramp works with an address on a chain only once the address has signed its fixed message, `I hereby declare that I am the address owner.`, for the customer.

- **Your tenant's Aurea wallets mode must be on** in the environment (`403` `BANK_RAMP_MODE_OFF`), and `network` one it offers (`400` `BANK_RAMP_PAIR_UNAVAILABLE`, with `details.available`); the user must be a confirmed customer (`404` `BANK_RAMP_CUSTOMER_NOT_FOUND`).
- `network` is `ethereum`, `gnosis`, `polygon`, `arbitrum` or `base`; in the sandbox it is that chain's test network.
- **The wallet** must be the user's (`404` `BANK_RAMP_WALLET_NOT_FOUND`), of the environment, an EVM account someone can sign for. Otherwise `409` `BANK_RAMP_WALLET_NOT_SIGNABLE` with `details.reason`: `environment`, `chain` (not EVM), `watch_only` (nobody signs for it) or `contract` — a contract wallet signs for itself: prove it as an address ([Ask for a Challenge](https://docs.aureahub.com/docs/bank-customer-address-challenge.md)).
- **Who signs:**

  - a **custodial** wallet: Aurea signs with the wallet's key and links it at once — `201`, `status` `linked` (or `202` `pending` while the bank ramp checks it);
  - a **client-side** or **MPC** wallet: `202`, `status` `awaiting_signature`, with `message` and its EIP-191 `digest` — the device signs `message` with `personal_sign`, an MPC ceremony signs `digest` — and `expiresAt`, 15 minutes. Send the signature to [Send a Link Signature](https://docs.aureahub.com/docs/bank-customer-wallet-signature.md).
- A frozen tenant, user or wallet answers `423` before anything is signed or handed out ([Freezes & Quarantines](https://docs.aureahub.com/docs/guide-freezes.md)). The message goes through your tenant's [signing rules](https://docs.aureahub.com/docs/guide-signing-rules.md) like any message a wallet signs; Aurea's built-in rules allow this one.
- **One link per address and chain.** A live link there — awaiting, pending or linked — is answered as it is (`200`); an expired one is replaced by a new one. A link the bank ramp refused is `failed` with `failureCode`, and a new call tries again.
- **Retries.** An `Idempotency-Key` header answers a repeated call with the first answer ([Idempotency](https://docs.aureahub.com/docs/idempotency.md)).
- While your tenant's [audit trail](https://docs.aureahub.com/docs/audit-events.md) is on, a link that becomes `linked` is recorded as `bank_ramp_address.linked` (category `security`) — never the address or the signature.

## Endpoint

### `POST /v1/ramp/bank/customer/wallets`

Authentication: bearer token required.

Links one of the user's Aurea wallets to their bank ramp customer on a chain.

**Request body**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `walletId` | string | yes | One of the user's Aurea wallets (UUID) |
| `network` | string | yes | `ethereum`, `gnosis`, `polygon`, `arbitrum` or `base` |
| `isTestnet` | boolean | no | `true` for the sandbox; `false` or omitted for production. The wallet must be of the same environment |

**Responses**

`202` Sign it (client-side, MPC)

```json
{
  "linkId": "9e3b6a1f-4c2d-4e8b-a7f0-5d1c3b9e2a64",
  "walletId": "0b7d2e4f-6a8c-4e1b-9d3f-2c5a7e9b1d40",
  "address": "0xC0207704CaEB9342cf491Ad4a177F43592df65a7",
  "network": "gnosis",
  "environment": "sandbox",
  "signer": "client",
  "status": "awaiting_signature",
  "message": "I hereby declare that I am the address owner.",
  "digest": "0xb77c35c892a1b24b10a2ce49b424e578472333ee8d2456234fff90626332c50f",
  "expiresAt": "2026-10-14T09:45:00.000Z",
  "failureCode": null,
  "linkedAt": null,
  "createdAt": "2026-10-14T09:30:00.000Z"
}
```

`201` Linked (custodial)

```json
{
  "linkId": "4a8c2e6f-1b3d-4f7a-9c5e-0d2b4f6a8c1e",
  "walletId": "7f1d3b5a-9c2e-4d6f-8a0b-3e5c7a9f1b24",
  "address": "0x8Ba1f109551bD432803012645Ac136ddd64DBA72",
  "network": "base",
  "environment": "sandbox",
  "signer": "server",
  "status": "linked",
  "message": null,
  "digest": null,
  "expiresAt": null,
  "failureCode": null,
  "linkedAt": "2026-10-14T09:30:02.000Z",
  "createdAt": "2026-10-14T09:30:01.000Z"
}
```

`409` Cannot sign

```json
{
  "statusCode": 409,
  "error": "ConflictError",
  "message": "Nobody can sign for this wallet.",
  "details": { "code": "BANK_RAMP_WALLET_NOT_SIGNABLE", "reason": "watch_only" }
}
```

`403` Mode off

```json
{
  "statusCode": 403,
  "error": "ForbiddenError",
  "message": "The bank ramp's Aurea wallets mode is not switched on for this tenant in sandbox.",
  "details": { "code": "BANK_RAMP_MODE_OFF", "mode": "aureaWallets", "environment": "sandbox" }
}
```

`400` Chain not offered

```json
{
  "statusCode": 400,
  "error": "BadRequestError",
  "message": "arbitrum is not available with the bank ramp in sandbox for this tenant. Available: gnosis, base.",
  "details": { "code": "BANK_RAMP_PAIR_UNAVAILABLE", "environment": "sandbox", "network": "arbitrum", "available": ["gnosis", "base"] }
}
```

## Implementation

```javascript
// A client-side wallet (ethers v6 signer on the device)
async function linkWallet(token, walletId, signer) {
  const link = await fetch('https://api.aureahub.com/v1/ramp/bank/customer/wallets', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
    body: JSON.stringify({ isTestnet: true, walletId, network: 'gnosis' })
  }).then((r) => r.json());
  if (link.status !== 'awaiting_signature') return link; // linked, pending, or failed

  const signature = await signer.signMessage(link.message); // EIP-191 personal_sign
  return fetch(`https://api.aureahub.com/v1/ramp/bank/customer/wallets/${link.linkId}/signature`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
    body: JSON.stringify({ signature })
  }).then((r) => r.json());
}
```

---

Web version: https://docs.aureahub.com/#bank-customer-wallet-link
