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

> ## Agent Instructions
> HEVN is payments software: an API and app over a Base smart wallet. HEVN is not a bank and holds no key to the wallet. Virtual accounts, fiat payins and fiat payouts are provided by partner banks, which hold fiat while it is in transit. Self-serve (the General tab): the person who controls the email signs for the wallet. Developers integrate /dapi/v1 in one of two ways. HEVN Connect (recommended, the HEVN Connect tab): the integrator's customer creates or links a HEVN account in a HEVN-hosted sign-in window on the integrator's site, the integrator's backend reads the linked account and books its payouts, and the account holder approves each payout in that window. External wallets (the External wallets tab, enabled per integrator): the integrator creates a client through the API, registers a wallet address the customer holds as an external account, and requests virtual accounts that deliver to that address. The customer's own wallet sends each transfer that funds a payout. The developer key signs for the integrator's wallet and its sub accounts and cannot sign for a client's wallet.
> Use HEVN's terms as written. A product is the region a client requests. A rail is the bank route HEVN picks for the product. A virtual account (bnk_) is the record a partner bank opens for a client. Account details are what a payer needs to send a bank transfer, returned in a field named requisites. A client (cl_) is a customer's account: linked to the integrator through Sign in with HEVN (POST /dapi/v1/connect/sessions, then POST /dapi/v1/clients/link), or created with POST /dapi/v1/clients for an external-wallets integration. An external account (acc_, kind external) is a wallet address the client holds and signs for. A sub account (acc_, kind sub) is a further wallet of the integrator's own account on Base, spent with the developer key. Write 'sub account' as two words. A contact is a saved destination. A beneficiary is the party that receives a fiat payout. Money leaving an account is a payout, whether it goes to a bank account or to a wallet.
> Do not name a bank, payment institution, card issuer, identity-verification vendor or stablecoin issuer. Say 'the partner bank'. Do not describe HEVN as licensed, regulated or insured.
> HEVN publishes no fee rates, spreads or minimums. Prices come from a quote on a specific payment. Direct pricing questions to HEVN and do not invent numbers.
> The API is at /dapi/v1 and takes a developer-key session plus an X-Hevn-Account header. Developer keys have an IP allowlist and no scopes. Remote transfers are at /api/v1/remote_spend_limit and take a remote transfer key (rsl_) in X-Api-Key, bounded by an onchain spend permission the account holder grants. The two credentials are separate and neither works on the other API. The HEVN CLI is discontinued.

# Payins

> Quote an incoming payment, give the payer instructions, and follow it to settlement.

A payin is an arrival of money on a Base smart wallet, a sub account or an external account, recorded as an income row on the ledger. To fix the rate and fee before the payer pays, quote it with `POST /dapi/v1/payins`.

| Shape | Call | Payer needs |
| - | - | - |
| Quoted bank payin | `POST /dapi/v1/payins` with `rail` | The instructions, with `paymentReference` |
| Quoted on-chain transfer | `POST /dapi/v1/payins` with `originChainId` | `address`, `chainId` and `memo` |
| Unsolicited wire | None | `requisites` of an active virtual account |
| Direct crypto | None | `baseSmartWallet` |

Send `X-Hevn-Account` to act for a client ([Acting as a client](https://docs.gethevn.com/developers/authentication.md#acting-as-a-client)).

## Quote a bank payin

The client needs an active [virtual account](https://docs.gethevn.com/developers/virtual-accounts.md) in the payer's currency.

**1. Create the quote**

Call `POST /dapi/v1/payins`.

```bash cURL theme={null}
curl -s -X POST "$HEVN_API/payins" \
  -H "Authorization: Bearer $HEVN_ACCESS_TOKEN" \
  -H "X-Hevn-Account: $HEVN_CLIENT_ID" \
  -H "Content-Type: application/json" \
  -d '{"amount":"2000.00","currency":"EUR","rail":"sepa","destinationAccount":"EURC"}'
```

```python Python theme={null}
payin = client.post("/payins", {
    "amount": "2000.00",
    "currency": "EUR",
    "rail": "sepa",
    "destinationAccount": "EURC",
})
```

```javascript Node theme={null}
const payin = await client.post("/payins", {
  amount: "2000.00",
  currency: "EUR",
  rail: "sepa",
  destinationAccount: "EURC",
});
```

```go Go theme={null}
payin, err := client.Post("/payins", hevn.Body{
	"amount":          "2000.00",
	"currency":        "EUR",
	"rail":            "sepa",
	"destinationAccount": "EURC",
})
```

```json Response: 201, Location: /dapi/v1/payins/pi_2b7… theme={null}
{ "id": "pi_2b7…", "status": "pending", "rail": "sepa",
  "quote": { "settlementAmount": "1989.50", "feeAmount": "10.50",
             "feeCurrency": "EUR", "rate": "1.0000", … },
  "expiresAt": "2026-09-17T10:06:11Z", … }
```

Field rules are in [Create an incoming transfer quote](https://docs.gethevn.com/api-reference/transfers/create-an-incoming-transfer-quote.md). Payment methods are listed in [Rails](https://docs.gethevn.com/developers/reference/rails.md#what-each-method-needs).

**2. Request the instructions**

Call `POST /dapi/v1/payins/{payinId}/instructions`.

```bash cURL theme={null}
curl -s -X POST "$HEVN_API/payins/pi_2b7…/instructions" \
  -H "Authorization: Bearer $HEVN_ACCESS_TOKEN" \
  -H "X-Hevn-Account: $HEVN_CLIENT_ID" \
  -H "Content-Type: application/json" -d '{}'
```

```python Python theme={null}
instructions = client.post(f"/payins/{payin['id']}/instructions", {})
```

```javascript Node theme={null}
const instructions = await client.post(`/payins/${payin.id}/instructions`, {});
```

```go Go theme={null}
instructions, err := client.Post("/payins/"+payin.Str("id")+"/instructions", hevn.Body{})
```

```json Response: 200 theme={null}
{ "payinId": "pi_2b7…", "kind": "bank_transfer",
  "amount": "2000.00", "currency": "EUR",
  "paymentReference": "HEVN-7QF3K2", "singleUse": true,
  "requisites": { "fields": { "iban": "DE89…", "bic": "BANKDEFFXXX" }, … } }
```

Do not reuse the instructions for a second payment. Fields are in [Open the incoming transfer](https://docs.gethevn.com/api-reference/transfers/open-the-incoming-transfer-and-retrieve-funding-instructions.md).

## Statuses

Poll `GET /dapi/v1/payins/{payinId}` until the status is final ([Status codes](https://docs.gethevn.com/developers/conventions.md#status-codes)).

| `status` | Meaning | Next |
| - | - | - |
| `pending` | Quoted. No money has arrived. A `rail` quote holds for 2 minutes at most. | Request the instructions before `expiresAt`. After it, the call returns `410 payin_expired`. |
| `awaitingFunds` | Instructions issued. The partner bank sets `expiresAt`. | Wait for the payer. Money that arrives after `expiresAt` can be returned to the payer. |
| `processing` | The partner bank has the money and is converting it. | Keep polling. |
| `inReview` | Held for an information request about the payment. | Keep polling. |
| `completed` | The tokens are on the destination. | n/a |
| `failed`, `canceled` | The money will not arrive. | Quote again. |
| `refunded` | Returned to the payer. | n/a |

An unpaid payin expires without a charge and has no ledger row. No route lists payins, so store `payinId` when you quote.

Once money arrives, a `pending` income row appears on the [ledger](https://docs.gethevn.com/developers/balances-and-transactions.md). It shows `rfi` while the partner bank asks about the payment and ends as `success` or `refunded`.

## Payer mistakes

| Mistake | Result |
| - | - |
| Bank transfer, different amount, right currency and reference | The amount sent is usually credited. The partner bank may return it instead. |
| Bank transfer, wrong currency or missing reference | The money may not be attributable. Recovery goes through HEVN support and is slow. |
| On-chain, different amount | Returned to the sender. |
| On-chain, wrong chain or token | The money does not arrive. Recovery is handled case by case with HEVN and is slow. |

For a payer who types the details by hand, use [unsolicited wires](#unsolicited-wires-to-the-clients-account-details).

## Quote an on-chain transfer

Send `originChainId` in place of `rail`.

```json theme={null}
{ "amount": "2000.00", "currency": "USDC", "originChainId": "arb", "destinationAccount": "USDC" }
```

The instructions call returns:

```json Response: 200 theme={null}
{ "kind": "onchain", "address": "0x9b41…", "chainId": "arb", "memo": null, … }
```

Give the payer `memo` when it is set. Chain values are in [Chain codes](https://docs.gethevn.com/developers/reference/rails.md#chain-codes).

## Deliver to an account

`destinationAccount` also takes the `acc_…` id of an [external account or a sub account](https://docs.gethevn.com/developers/accounts.md). The payin is then an on-chain transfer, so send `originChainId`.

```json theme={null}
{ "amount": "2000.00", "currency": "USDC", "originChainId": "arb",
  "destinationAccount": "acc_5Jd8Qw2LmX", "refundAddress": "0x51a7…" }
```

| Rule | External account | Sub account |
| - | - | - |
| `rail` | `409 account_destination_unsupported` | `409 account_destination_unsupported` |
| `refundAddress` | Required. The address on the origin chain that receives the funds back when the transfer cannot be completed. Without it the call returns `422 refund_address_required`. | Ignored. A sub account is refunded as the main wallet is. |
| Delivered | USDC on the account's network, to its address | The token the account holds, on Base, to its address |
| Response | `accountId` names the account | `accountId` names the account |

`refundAddress` with an account key as `destinationAccount` returns `422 validation_failed`. See [External wallets](https://docs.gethevn.com/external-wallets/money-movement.md) and [Sub accounts](https://docs.gethevn.com/sub-accounts/money-movement.md).

## Payer details

Some rails require the payer's account. Send it as `payer` on the instructions call.

```json theme={null}
{ "payer": { "method": "sepa",
             "requisites": { "method": "sepa", "currency": "EUR",
                             "fields": { "iban": "DE89370400440532013000", "bic": "BANKDEFFXXX" },
                             "holder": { "type": "business", "businessName": "Payer GmbH" } } } }
```

`details.options[].payerRequired` on a refused quote shows which pairs need a payer.

## Refusals

| Error | Next |
| - | - |
| `422 payin_not_available` | Quote again with a pair from `details.options[]`. Each option has `rail`, `currency`, `available`, `minAmount`, `maxAmount`, `feeBps`, `fixedFee`, `payerRequired` and `destinationAccounts`. |
| `400 invalid_request` | Send `payer` with the identifiers in `details.fields`. |
| `410 payin_expired` | Quote again. |

Other codes are in [Errors](https://docs.gethevn.com/developers/reference/errors.md#rails-and-payins). Indicative rates are in [Fees](https://docs.gethevn.com/developers/reference/rails.md#fees).

## Unsolicited wires to the client's account details

A payer can send to an active virtual account at any time. Give the payer its [account details](https://docs.gethevn.com/developers/virtual-accounts.md#account-details) from `GET /dapi/v1/banks`, with `paymentReference` when one is set.

The income row from `GET /dapi/v1/transactions` has `paymentReference`, the receiving account details and `remitter`.

> [!NOTE]
>
> `remitter` is set when the partner bank reports the sender. When it is absent on a settled row, the API cannot return the sender.

## Direct crypto

Read `baseSmartWallet` from `GET /dapi/v1/client/balance` and give the address to the payer. A sub account takes a transfer of its token at its `address` in the same way ([Sub accounts](https://docs.gethevn.com/sub-accounts/money-movement.md)).

> [!WARNING]
>
> HEVN tracks USDC and EURC on Base. Other tokens, and these tokens on other chains, do not become a balance or a transaction.

## Sandbox

A quoted payin does not settle until you call the route in [Settle a payin](https://docs.gethevn.com/developers/sandbox.md#settle-a-payin). For the unquoted shapes, see [Mint money](https://docs.gethevn.com/developers/sandbox.md#mint-money).

> [card] [Next: Payouts](https://docs.gethevn.com/developers/payouts.md)


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