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

# Send Within Nuvion

> Send funds from one Nuvion account to another with a book transfer, whether the accounts belong to you, to a parent and its children, or to different entities.

This guide sends funds from one Nuvion account to another. It ends with a `successful` book transfer: the amount leaves your account and arrives in the recipient's account straight away.

All you need is the recipient's Nuvion account number. The recipient can be another account of your own, a parent or child entity, another entity under the same parent, or any other Nuvion customer, such as a supplier or a customer of yours who also banks with Nuvion. Sending from a child entity's account works the same way, with one addition: see [Send from or to a child entity](#send-from-or-to-a-child-entity).

## When to use a book transfer

If the recipient banks with Nuvion, prefer a book transfer. It settles immediately, needs no routing details, and doesn't pass through an external payment rail. Use a [bank payout](https://docs.nuvion.co/guides/send-a-payout.md) when the recipient banks elsewhere.

## How it differs from other payouts

A book transfer follows the same three steps as any [payout](https://docs.nuvion.co/guides/send-a-payout.md): create a counterparty, add a payment detail, then send the transfer. These points differ:

| | Book transfer |
| - | - |
| Recipient identifier | The recipient's Nuvion account number, which is the `nuvion_ban` of their account. Ask the recipient for it. |
| Routing fields | None. Don't send `country`, `scheme` or `bank_name`. Nuvion sets `scheme` to `nuvion_direct` and `bank_name` to `Nuvion Payments LLC`. |
| Currency | The currency of the recipient's account. It must match the account. |
| Settlement | Immediate. The transfer is `successful` in the response. |
| Fee | The sender pays `applicable_fee` on top of `amount`. Fees come from your fee rules, so check your pricing sheet. |
| Amount | A whole number of at least `1`, in minor units. Nuvion enforces no other limit. |

## Before you start

* An API key, and the `account_id` of the account that pays. It needs a balance of at least the amount plus the fee.
* The recipient's `nuvion_ban` and the currency of that account.

The examples use these placeholder values. Replace them with your own.

| Placeholder | What it is |
| - | - |
| `01HXYZ2000ABCDEFGHJKMNPQRS` | The ID of your entity. You send it only when you act for a child entity. |
| `01HXYZ3000ABCDEFGHJKMNPQRS` | The counterparty ID that Step 1 returns. |
| `01HXYZ4000ABCDEFGHJKMNPQRS` | The ID of your account that pays. |
| `01HXYZ5000ABCDEFGHJKMNPQRS` | The payment detail ID that Step 2 returns. |
| `01HXYZ6000ABCDEFGHJKMNPQRS` | The transfer ID that Step 3 returns. |
| `0010650099` | The recipient's `nuvion_ban`. |

## Step 1: Create a counterparty

Create a counterparty for the recipient. Do this once per recipient.

```bash curl theme={null}
# Run this once per recipient.
curl -X POST https://api.nuvion.dev/counterparties \
  -H "Authorization: Bearer $NUVION_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "business",
    "nickname": "Northwind Supplies",
    "profile": {
      "legal_name": "Northwind Supplies Ltd",
      "relationship": "supplier",
      "email": "accounts@northwind.example",
      "registered_address": {
        "line1": "12 Market Street",
        "city": "London",
        "postal_code": "EC1A 1BB",
        "country": "GB"
      }
    }
  }'
```

```json 201 Created theme={null}
{
  "status": "success",
  "message": "Counterparty created successfully",
  "data": {
    "id": "01HXYZ3000ABCDEFGHJKMNPQRS",
    "entity_id": "01HXYZ2000ABCDEFGHJKMNPQRS",
    "type": "business",
    "nickname": "Northwind Supplies",
    "status": "active",
    "profile": {
      "legal_name": "Northwind Supplies Ltd",
      "relationship": "supplier",
      "registered_address": {
        "line1": "12 Market Street",
        "city": "London",
        "postal_code": "EC1A 1BB",
        "country": "GB"
      },
      "email": "accounts@northwind.example"
    },
    "created": 1793813735899,
    "updated": 1793813735899,
    "deleted": 0
  }
}
```

```json 422 Missing field theme={null}
{
  "status": "error",
  "message": "Validation failed for one or more fields",
  "type": "error_validation_error",
  "validations": [
    {
      "profile": {
        "type": "error_validation_required_field_missing",
        "message": "The 'profile' field is required. Please include it and try again."
      }
    }
  ]
}
```

```json 401 Invalid key theme={null}
{
  "status": "error",
  "message": "Your credentials are invalid or have expired. Please check your credentials and try again",
  "type": "error_auth_credentials_invalid"
}
```

Keep `data.id` (`01HXYZ3000ABCDEFGHJKMNPQRS`). Step 2 and Step 3 use it as `counterparty_id`. See [Create a counterparty](https://docs.nuvion.co/api-reference/counterparties.md#create-a-counterparty).

## Step 2: Add the recipient's account as a payment detail

Add a `book-transfer` payment detail whose `account_number` is the recipient's `nuvion_ban`. Nuvion checks that the number belongs to a Nuvion account when you add it.

```bash curl theme={null}
# Run this once per recipient account. account_number is the recipient's nuvion_ban.
curl -X POST https://api.nuvion.dev/payment-details \
  -H "Authorization: Bearer $NUVION_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "payment_method": "book-transfer",
    "currency": "GBP",
    "account_holder_name": "Northwind Supplies Ltd",
    "counterparty_id": "01HXYZ3000ABCDEFGHJKMNPQRS",
    "account_number": "0010650099"
  }'
```

```json 201 Created theme={null}
{
  "status": "success",
  "message": "Payment detail created successfully",
  "data": {
    "id": "01HXYZ5000ABCDEFGHJKMNPQRS",
    "payment_method": "book-transfer",
    "currency": "GBP",
    "account_holder_name": "Northwind Supplies Ltd",
    "counterparty_id": "01HXYZ3000ABCDEFGHJKMNPQRS",
    "entity_id": "01HXYZ2000ABCDEFGHJKMNPQRS",
    "scheme": "nuvion_direct",
    "account_number": "0010650099",
    "bank_name": "Nuvion Payments LLC",
    "meta": {}
  }
}
```

```json 422 Unknown account number theme={null}
{
  "status": "error",
  "message": "Validation failed for one or more fields",
  "type": "error_validation_error",
  "validations": [
    {
      "account_number": {
        "type": "error_resource_not_found",
        "message": "We couldn't find that account. It may have been deleted or the ID might be incorrect."
      }
    }
  ]
}
```

```json 422 Duplicate account number theme={null}
{
  "status": "error",
  "message": "Validation failed for one or more fields",
  "type": "error_validation_error",
  "validations": [
    {
      "account_number": {
        "type": "error_duplicate_resource",
        "message": "A record with this account number already exists. Please use different details or check your existing records."
      }
    }
  ]
}
```

```json 422 Counterparty not found theme={null}
{
  "status": "error",
  "message": "Validation failed for one or more fields",
  "type": "error_validation_error",
  "validations": [
    {
      "counterparty_id": {
        "type": "error_resource_not_found",
        "message": "We couldn't find that counterparty. It may have been deleted or the ID might be incorrect."
      }
    }
  ]
}
```

Keep `data.id` (`01HXYZ5000ABCDEFGHJKMNPQRS`). Step 3 uses it as `payment_detail_id`. See [Create payment details](https://docs.nuvion.co/api-reference/payment-details.md).

## Step 3: Send the transfer

Create a `book-transfer` from your account. `amount` is in minor units. Use a new `unique_reference` for each payment.

```bash curl theme={null}
# Run this for every payment. The amount excludes the fee.
curl -X POST https://api.nuvion.dev/transfers \
  -H "Authorization: Bearer $NUVION_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "01HXYZ4000ABCDEFGHJKMNPQRS",
    "counterparty_id": "01HXYZ3000ABCDEFGHJKMNPQRS",
    "payment_detail_id": "01HXYZ5000ABCDEFGHJKMNPQRS",
    "amount": 5000,
    "currency": "GBP",
    "narration": "Invoice 1042",
    "payment_type": "book-transfer",
    "unique_reference": "PAY-2026-0001"
  }'
```

```javascript Node.js theme={null}
const res = await fetch("https://api.nuvion.dev/transfers", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.NUVION_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    account_id: "01HXYZ4000ABCDEFGHJKMNPQRS", // your account that pays
    counterparty_id: "01HXYZ3000ABCDEFGHJKMNPQRS", // from Step 1
    payment_detail_id: "01HXYZ5000ABCDEFGHJKMNPQRS", // from Step 2
    amount: 5000, // minor units, so 5000 is GBP 50.00, not including the fee
    currency: "GBP",
    narration: "Invoice 1042",
    payment_type: "book-transfer",
    unique_reference: "PAY-2026-0001", // use a new value for every payment
  }),
});
console.log(res.status, await res.json());
```

```python Python theme={null}
import os
import requests

res = requests.post(
    "https://api.nuvion.dev/transfers",
    headers={"Authorization": f"Bearer {os.environ['NUVION_API_KEY']}"},
    json={
        "account_id": "01HXYZ4000ABCDEFGHJKMNPQRS",  # your account that pays
        "counterparty_id": "01HXYZ3000ABCDEFGHJKMNPQRS",  # from Step 1
        "payment_detail_id": "01HXYZ5000ABCDEFGHJKMNPQRS",  # from Step 2
        "amount": 5000,  # minor units, so 5000 is GBP 50.00, not including the fee
        "currency": "GBP",
        "narration": "Invoice 1042",
        "payment_type": "book-transfer",
        "unique_reference": "PAY-2026-0001",  # use a new value for every payment
    },
)
print(res.status_code, res.json())
```

```ruby Ruby theme={null}
require "net/http"
require "json"

uri = URI("https://api.nuvion.dev/transfers")
req = Net::HTTP::Post.new(uri, "Authorization" => "Bearer #{ENV['NUVION_API_KEY']}", "Content-Type" => "application/json")
req.body = {
  "account_id" => "01HXYZ4000ABCDEFGHJKMNPQRS",  # your account that pays
  "counterparty_id" => "01HXYZ3000ABCDEFGHJKMNPQRS",  # from Step 1
  "payment_detail_id" => "01HXYZ5000ABCDEFGHJKMNPQRS",  # from Step 2
  "amount" => 5000,  # minor units, so 5000 is GBP 50.00, not including the fee
  "currency" => "GBP",
  "narration" => "Invoice 1042",
  "payment_type" => "book-transfer",
  "unique_reference" => "PAY-2026-0001",  # use a new value for every payment
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts "#{res.code} #{res.body}"
```

```php PHP theme={null}
<?php
$ch = curl_init("https://api.nuvion.dev/transfers");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("NUVION_API_KEY"),
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "account_id" => "01HXYZ4000ABCDEFGHJKMNPQRS", // your account that pays
        "counterparty_id" => "01HXYZ3000ABCDEFGHJKMNPQRS", // from Step 1
        "payment_detail_id" => "01HXYZ5000ABCDEFGHJKMNPQRS", // from Step 2
        "amount" => 5000, // minor units, so 5000 is GBP 50.00, not including the fee
        "currency" => "GBP",
        "narration" => "Invoice 1042",
        "payment_type" => "book-transfer",
        "unique_reference" => "PAY-2026-0001", // use a new value for every payment
    ]),
]);
$body = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE), " ", $body, "\n";
```

```go Go theme={null}
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	payload, _ := json.Marshal(map[string]any{
		"account_id":        "01HXYZ4000ABCDEFGHJKMNPQRS", // your account that pays
		"counterparty_id":   "01HXYZ3000ABCDEFGHJKMNPQRS", // from Step 1
		"payment_detail_id": "01HXYZ5000ABCDEFGHJKMNPQRS", // from Step 2
		"amount":            5000,                         // minor units, so 5000 is GBP 50.00, not including the fee
		"currency":          "GBP",
		"narration":         "Invoice 1042",
		"payment_type":      "book-transfer",
		"unique_reference":  "PAY-2026-0001", // use a new value for every payment
	})
	req, _ := http.NewRequest("POST", "https://api.nuvion.dev/transfers", bytes.NewReader(payload))
	req.Header.Set("Authorization", "Bearer "+os.Getenv("NUVION_API_KEY"))
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(res.StatusCode, string(body))
}
```

```java Java theme={null}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class PayNuvionAccount {
    public static void main(String[] args) throws Exception {
        String json = "{"
            // your account that pays
            + "\"account_id\": \"01HXYZ4000ABCDEFGHJKMNPQRS\","
            // from Step 1
            + "\"counterparty_id\": \"01HXYZ3000ABCDEFGHJKMNPQRS\","
            // from Step 2
            + "\"payment_detail_id\": \"01HXYZ5000ABCDEFGHJKMNPQRS\","
            // minor units, so 5000 is GBP 50.00, not including the fee
            + "\"amount\": 5000,"
            + "\"currency\": \"GBP\","
            + "\"narration\": \"Invoice 1042\","
            + "\"payment_type\": \"book-transfer\","
            // use a new value for every payment
            + "\"unique_reference\": \"PAY-2026-0001\""
            + "}";
        HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.nuvion.dev/transfers"))
            .header("Authorization", "Bearer " + System.getenv("NUVION_API_KEY"))
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(json))
            .build();
        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.statusCode() + " " + response.body());
    }
}
```

```csharp C# theme={null}
using System.Net.Http.Json;

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + Environment.GetEnvironmentVariable("NUVION_API_KEY"));

var res = await client.PostAsJsonAsync("https://api.nuvion.dev/transfers", new
{
    account_id = "01HXYZ4000ABCDEFGHJKMNPQRS", // your account that pays
    counterparty_id = "01HXYZ3000ABCDEFGHJKMNPQRS", // from Step 1
    payment_detail_id = "01HXYZ5000ABCDEFGHJKMNPQRS", // from Step 2
    amount = 5000, // minor units, so 5000 is GBP 50.00, not including the fee
    currency = "GBP",
    narration = "Invoice 1042",
    payment_type = "book-transfer",
    unique_reference = "PAY-2026-0001", // use a new value for every payment
});
Console.WriteLine($"{(int)res.StatusCode} {await res.Content.ReadAsStringAsync()}");
```

```json 201 Created theme={null}
{
  "status": "success",
  "message": "Transfer created successfully",
  "data": {
    "id": "01HXYZ6000ABCDEFGHJKMNPQRS",
    "amount": 5000,
    "currency": "GBP",
    "unique_reference": "PAY-2026-0001",
    "counterparty_id": "01HXYZ3000ABCDEFGHJKMNPQRS",
    "account_id": "01HXYZ4000ABCDEFGHJKMNPQRS",
    "entity_id": "01HXYZ2000ABCDEFGHJKMNPQRS",
    "status": "successful",
    "status_reason": "processing_complete",
    "narration": "Invoice 1042",
    "type": "outflow",
    "payment_type": "book-transfer",
    "applicable_fee": 500,
    "meta": {
      "provider_reference": null
    },
    "created": 1793813763827,
    "updated": 1793813765868
  }
}
```

```json 409 Duplicate reference theme={null}
{
  "status": "error",
  "message": "A record with this unique_reference, entity_id already exists. Please use different details or check your existing records.",
  "type": "error_duplicate_resource"
}
```

```json 400 Insufficient funds theme={null}
{
  "status": "error",
  "message": "You don't have enough funds for this transfer. Your available balance is 90,917.82 GBP.",
  "type": "error_transfer_insufficient_funds"
}
```

```json 400 Currency mismatch theme={null}
{
  "status": "error",
  "message": "You can't perform this action right now due to the current status. Please try again later or contact support.",
  "type": "error_operation_invalid_for_state"
}
```

```json 400 Same account theme={null}
{
  "status": "error",
  "message": "You can't perform this action right now due to the current status. Please try again later or contact support.",
  "type": "error_operation_invalid_for_state"
}
```

```json 404 Not found theme={null}
{
  "status": "error",
  "message": "We couldn't find that account | counterparty | payment_detail. It may have been deleted or the ID might be incorrect.",
  "type": "error_resource_not_found"
}
```

```json 422 Amount is zero theme={null}
{
  "status": "error",
  "message": "Validation failed for one or more fields",
  "type": "error_validation_error",
  "validations": [
    {
      "amount": {
        "type": "error_validation_value_out_of_range",
        "message": "The value for 'amount' should be between 1 and 9007199254740991."
      }
    }
  ]
}
```

```json 422 Amount not whole theme={null}
{
  "status": "error",
  "message": "Validation failed for one or more fields",
  "type": "error_validation_error",
  "validations": [
    {
      "amount": {
        "type": "error_validation_invalid_format",
        "message": "The 'amount' format isn't valid. Please use the correct format."
      }
    }
  ]
}
```

```json 401 Invalid key theme={null}
{
  "status": "error",
  "message": "Your credentials are invalid or have expired. Please check your credentials and try again",
  "type": "error_auth_credentials_invalid"
}
```

The transfer is `successful` straight away, because a book transfer settles immediately. `applicable_fee` is the fee debited from your account on top of `amount`, in minor units. See [Create a transfer](https://docs.nuvion.co/api-reference/transfers.md) for every field and error.

## Scenarios

The three steps are the same in every scenario. What changes is the key you use, whether you send `entity_id`, and whose `nuvion_ban` goes in Step 2.

| Scenario | When to use it | API key | `entity_id` | Recipient account (Step 2) |
| - | - | - | - | - |
| Between two of your own accounts | Move money between your operating account and a payroll or tax account. | Yours | Leave out | Other account's `nuvion_ban` |
| To another Nuvion customer | Pay a supplier or partner that also banks with Nuvion. They have the funds straight away. | Yours | Leave out | Their `nuvion_ban` |
| From a child to its parent | Move surplus cash from a subsidiary or branch to head office (a sweep). | The parent's | Child's ID, every call | Parent's `nuvion_ban` |
| From a parent to a child | Fund a new subsidiary or top up a branch's operating float. | The parent's | Leave out | Child's `nuvion_ban` |
| Between two children of one parent | Settle intercompany charges, such as one subsidiary billing another for shared services. | The parent's | Paying child's ID, every call | Other child's `nuvion_ban` |
| From a child to another customer | Let a subsidiary pay an outside vendor from its own account, so the expense stays on its books. | The parent's | Child's ID, every call | Their `nuvion_ban` |
| From another customer to a child | Let a client pay a specific subsidiary directly, so the revenue lands in the right entity. | Theirs | Leave out | Child's `nuvion_ban` |

Each tab shows Step 3 for one scenario.

```bash Own accounts theme={null}
# Your key.
# No entity_id.
# account_id is the account that pays; account_number in Step 2 is your other account's nuvion_ban.
curl -X POST https://api.nuvion.dev/transfers \
  -H "Authorization: Bearer $NUVION_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "01HXYZ4000ABCDEFGHJKMNPQRS",
    "counterparty_id": "01HXYZ3000ABCDEFGHJKMNPQRS",
    "payment_detail_id": "01HXYZ5000ABCDEFGHJKMNPQRS",
    "amount": 5000,
    "currency": "GBP",
    "narration": "Transfer to payroll account",
    "payment_type": "book-transfer",
    "unique_reference": "PAY-2026-0001"
  }'
```

```bash Other customer theme={null}
# Your key.
# No entity_id.
# account_number in Step 2 is the other customer's nuvion_ban.
curl -X POST https://api.nuvion.dev/transfers \
  -H "Authorization: Bearer $NUVION_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "01HXYZ4000ABCDEFGHJKMNPQRS",
    "counterparty_id": "01HXYZ3000ABCDEFGHJKMNPQRS",
    "payment_detail_id": "01HXYZ5000ABCDEFGHJKMNPQRS",
    "amount": 5000,
    "currency": "GBP",
    "narration": "Invoice 1042",
    "payment_type": "book-transfer",
    "unique_reference": "PAY-2026-0001"
  }'
```

```bash Child to parent theme={null}
# The parent's key.
# entity_id is the child that pays, on every call.
# account_number in Step 2 is the parent account's nuvion_ban.
curl -X POST https://api.nuvion.dev/transfers \
  -H "Authorization: Bearer $NUVION_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "entity_id": "01HXYZ7000ABCDEFGHJKMNPQRS",
    "account_id": "01HXYZ4000ABCDEFGHJKMNPQRS",
    "counterparty_id": "01HXYZ3000ABCDEFGHJKMNPQRS",
    "payment_detail_id": "01HXYZ5000ABCDEFGHJKMNPQRS",
    "amount": 5000,
    "currency": "GBP",
    "narration": "Surplus to head office",
    "payment_type": "book-transfer",
    "unique_reference": "PAY-2026-0001"
  }'
```

```bash Parent to child theme={null}
# The parent's key.
# No entity_id, because the parent pays.
# account_number in Step 2 is the child account's nuvion_ban.
curl -X POST https://api.nuvion.dev/transfers \
  -H "Authorization: Bearer $NUVION_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "01HXYZ4000ABCDEFGHJKMNPQRS",
    "counterparty_id": "01HXYZ3000ABCDEFGHJKMNPQRS",
    "payment_detail_id": "01HXYZ5000ABCDEFGHJKMNPQRS",
    "amount": 5000,
    "currency": "GBP",
    "narration": "Monthly float top-up",
    "payment_type": "book-transfer",
    "unique_reference": "PAY-2026-0001"
  }'
```

```bash Between children theme={null}
# The parent's key.
# entity_id is the child that pays, on every call.
# account_number in Step 2 is the other child's nuvion_ban.
curl -X POST https://api.nuvion.dev/transfers \
  -H "Authorization: Bearer $NUVION_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "entity_id": "01HXYZ7000ABCDEFGHJKMNPQRS",
    "account_id": "01HXYZ4000ABCDEFGHJKMNPQRS",
    "counterparty_id": "01HXYZ3000ABCDEFGHJKMNPQRS",
    "payment_detail_id": "01HXYZ5000ABCDEFGHJKMNPQRS",
    "amount": 5000,
    "currency": "GBP",
    "narration": "Intercompany delivery charges",
    "payment_type": "book-transfer",
    "unique_reference": "PAY-2026-0001"
  }'
```

```bash Child to other customer theme={null}
# The parent's key.
# entity_id is the child that pays, on every call.
# account_number in Step 2 is the other customer's nuvion_ban.
curl -X POST https://api.nuvion.dev/transfers \
  -H "Authorization: Bearer $NUVION_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "entity_id": "01HXYZ7000ABCDEFGHJKMNPQRS",
    "account_id": "01HXYZ4000ABCDEFGHJKMNPQRS",
    "counterparty_id": "01HXYZ3000ABCDEFGHJKMNPQRS",
    "payment_detail_id": "01HXYZ5000ABCDEFGHJKMNPQRS",
    "amount": 5000,
    "currency": "GBP",
    "narration": "Office rent",
    "payment_type": "book-transfer",
    "unique_reference": "PAY-2026-0001"
  }'
```

```bash Other customer to child theme={null}
# The other customer's key.
# No entity_id.
# account_number in Step 2 is the child account's nuvion_ban.
curl -X POST https://api.nuvion.dev/transfers \
  -H "Authorization: Bearer $NUVION_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "01HXYZ4000ABCDEFGHJKMNPQRS",
    "counterparty_id": "01HXYZ3000ABCDEFGHJKMNPQRS",
    "payment_detail_id": "01HXYZ5000ABCDEFGHJKMNPQRS",
    "amount": 5000,
    "currency": "GBP",
    "narration": "Consulting fees",
    "payment_type": "book-transfer",
    "unique_reference": "PAY-2026-0001"
  }'
```

In every scenario the sender pays the fee on top of the amount, the recipient is credited the full amount, and the transfer is `successful` straight away.

### What the recipient sees

The recipient's account records an inflow with `payment_type` `book-transfer` and `status` `successful`. It carries the `amount`, the `currency` and your `narration`, so the recipient can reconcile it against an invoice or reference. It doesn't carry your request `meta`. Its `applicable_fee` follows the recipient's own pricing, not yours.

The recipient learns about it in either of two ways:

* **Webhook:** an [`inflows.completed`](https://docs.nuvion.co/webhooks/event-types#inflows-completed) event, if they subscribe to it.
* **API:** `GET /transfers?type=inflow&payment_type=book-transfer`, as described in [List transfers](https://docs.nuvion.co/api-reference/transfers.md#list-transfers).

## Send from or to a child entity

To send from a child entity's account, send the child's `entity_id` on every call, as described in [Managing child entities](https://docs.nuvion.co/core-concepts/entities.md#managing-child-entities). The recipient can be the parent: use the parent account's `nuvion_ban` as the `account_number`. Between a parent and its children, or between two children of the same parent, the flow is the same.

If you leave `entity_id` off Step 1, Nuvion creates the counterparty under the parent. Step 2 then returns `422` and Step 3 returns `404`, because the child can't see it.

## Handle errors

Each step's response box has a tab for every failure listed here, with the exact body Nuvion returns.

| Situation | Step | Status | `type` | What to do |
| - | - | - | - | - |
| A required field is missing, such as `profile` | 1 | `422` | `error_validation_error` | The `validations` array names the field. |
| The recipient's account number isn't a Nuvion account | 2 | `422` | `error_validation_error` | Check the `nuvion_ban` with the recipient. The `validations` array names `account_number` with `error_resource_not_found`. |
| The account number is already on the counterparty | 2 | `422` | `error_validation_error` | Reuse the payment detail you already created. The `validations` array names `account_number` with `error_duplicate_resource`. |
| The call leaves out the child's `entity_id` | 1 to 3 | none, `422`, `404` | `error_resource_not_found` | Send `entity_id` on every call when you act for a child. |
| The `unique_reference` was already used | 3 | `409` | `error_duplicate_resource` | The first request already went through, so don't send it again. Use a new reference for a new payment. |
| The amount plus the fee is more than the available balance | 3 | `400` | `error_transfer_insufficient_funds` | Send a smaller amount. The message shows the available balance. |
| The payment detail's currency doesn't match the recipient's account | 3 | `400` | `error_operation_invalid_for_state` | Add a new payment detail with the currency of the recipient's account. |
| The payment detail points at the account that pays | 3 | `400` | `error_operation_invalid_for_state` | Pay a different account. Nuvion returns the same response as for a currency mismatch. |
| The `amount` is `0`, negative or not a whole number | 3 | `422` | `error_validation_error` | Send a whole number of at least `1`. The `validations` array names `amount`. |
| The API key is wrong or belongs to the other environment | Any | `401` | `error_auth_credentials_invalid` | Use a key for the environment you are calling. |

`error_operation_invalid_for_state` has more than one cause, so check both the currency and the destination account when you see it.


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