Nexus API Reference

What is Nexus?

Nexus is a hosted crypto payment gateway. Merchants use it to accept cryptocurrency from their customers without running wallet, exchange-rate, or settlement infrastructure themselves. The service handles address generation, price conversion, confirmation tracking, and optional auto-conversion of received crypto into a preferred settlement currency.

Every endpoint in this document is a REST call made over HTTPS with a JSON body and an Authorization: Bearer <token> header. Responses are JSON.

Environments. Authentication (GraphQL, sign-in only): https://YOUR_EXCHANGE_HOST/graphql. Nexus API (REST): https://YOUR_NEXUS_HOST. Your Demo and Production hostnames are shared with your team during onboarding; substitute them wherever these placeholders appear below.

How It Works

  1. Merchant signs in. Exchange your API key and secret for a JWT Bearer token with Sign in for a bearer token. Every authenticated call carries this token. The exchange account must be active and have Nexus enabled, or calls return 403 User is not authorized.
  2. Merchant record exists. PATCH /v1/user/checkin creates the merchant record on first use and syncs currencies. The dashboard calls it on sign-in.
  3. Merchant creates a payment. POST /v1/payment creates an invoice or an openDeposit.
  4. An address is created for the customer. POST /v1/client/address returns (and on first use creates) the address for a currency/network pair. The customer sends funds to it.
  5. Service processes the deposit. Each update from the exchange about the transaction is recorded. Deposits become final when the exchange completes them. Invoices then move to Completed, Completed Loss, Completed Profit or Partially Completed. An openDeposit stays Processing.
  6. Service notifies the merchant. Every enabled webhook receives transaction deliveries (transaction_status Detected, ClientCompleted, Completed or Rejected), payment deliveries (when an invoice reaches Client Completed or a completed status, or when a status is set manually) and payout.* events. Each delivery is signed with x-webhook-signature = sha256(webhook_id + body) (see Register a webhook).
  7. Merchant pays out settled funds. Create a payout with POST /v1/payout, then approve it with PATCH /v1/payout/{payoutId}/approve. Approval needs a 2FA code unless skip_payout_mfa is on.

Two payment types

Both are created by the same endpoint. type decides the shape, and pricing_mode is required for both.

Scenario 1: Fixed Amount Invoice

Use this to charge the customer a specific amount in an order currency, for example 0.05 ETH for order #42. Unless passthrough_fees is true, the merchant and parent fees are added to the amount the customer must pay (target_currency_amount_required).

Step-by-step

  1. (Once) Register a webhook with POST /v1/webhook.
  2. List deposit currencies with GET /v1/currency.
  3. Create the invoice with POST /v1/payment:
    {
      "type": "invoice",
      "pricing_mode": "convertOnArrival",
      "amount_required": 0.05,
      "merchant_order_currency_id": "ETH",
      "merchant_order_id": "order-0001"
    }
  4. Create the pay-to address with POST /v1/client/address, passing payment_id, currency and currency_network, and show it to the customer.
  5. Wait for settlement on your webhook, or read GET /v1/payment/{id}. With custom confirmation counts, the payment can first reach Client Completed. Final statuses are Completed, Completed Loss (underpaid within the threshold, or a price move against the merchant) and Completed Profit (overpaid, or a price move in the merchant's favour). An underpayment beyond the threshold leaves the payment Partially Completed.

Scenario 2: Open Deposit

Use this to give a customer a reusable deposit address for any amount. Leave out amount_required and merchant_order_currency_id; both are ignored for this type. If you leave out expiration, the payment never expires.

Step-by-step

  1. (Once) Register a webhook with POST /v1/webhook.
  2. Create the open deposit once per customer:
    {
      "type": "openDeposit",
      "pricing_mode": "convertOnArrival",
      "merchant_order_id": "deposit-alice",
      "merchant_order_metadata": {
        "customer": "alice@example.com"
      }
    }
  3. Create the address with POST /v1/client/address for each currency/network pair you want to offer. Repeated calls return the same address.
  4. Credit the customer on the transaction delivery with transaction_status: "Completed". Credit once per (payment_id, crypto_transaction_id), because Completed is normally delivered twice. merchant_order_id and merchant_order_metadata are echoed in every delivery.

Authentication

Exchange your API key and secret for a short-lived JWT bearer token. Every other endpoint in this reference requires this token in the Authorization: Bearer <token> header. Tokens expire, so repeat this call to refresh.

POST /graphql Sign in for a bearer token

Calls the service_signin GraphQL mutation with your API key and secret. Returns a JWT and its expiration timestamp. Use the returned jwt as the Bearer token on every subsequent REST call.

Endpoint: POST https://YOUR_EXCHANGE_HOST/graphql
Content-Type: application/json

Variables

NameTypeRequiredDescription
service_api_key string required Your Nexus API key, issued by the platform.
service_api_secret string required Your Nexus API secret. Treat as a password and do not embed in client-side code.

Response

FieldTypeDescription
data.service_signin.jwt string The bearer token. Send as Authorization: Bearer <jwt> on every other endpoint.
data.service_signin.expires_at number Token expiration as a Unix timestamp. Re-sign to refresh before this time.

Code Examples

curl -X POST 'https://YOUR_EXCHANGE_HOST/graphql' \
  -H 'Content-Type: application/json' \
  -d '{"query":"mutation service_signin($key: String!, $secret: String!) { service_signin(service_api_key: $key, service_api_secret: $secret) { jwt expires_at } }","variables":{"key":"YOUR_API_KEY","secret":"YOUR_API_SECRET"}}'
import requests

url = "https://YOUR_EXCHANGE_HOST/graphql"
body = {
    "query": "mutation service_signin($key: String!, $secret: String!) { service_signin(service_api_key: $key, service_api_secret: $secret) { jwt expires_at } }",
    "variables": {"key": "YOUR_API_KEY", "secret": "YOUR_API_SECRET"},
}

response = requests.post(url, json=body)
jwt = response.json()["data"]["service_signin"]["jwt"]
print(jwt)
const response = await fetch("https://YOUR_EXCHANGE_HOST/graphql", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    query: "mutation service_signin($key: String!, $secret: String!) { service_signin(service_api_key: $key, service_api_secret: $secret) { jwt expires_at } }",
    variables: { key: "YOUR_API_KEY", secret: "YOUR_API_SECRET" },
  }),
});
const data = await response.json();
const jwt = data.data.service_signin.jwt;
console.log(jwt);

Example response

{
  "data": {
    "service_signin": {
      "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
      "expires_at": 1735689600
    }
  }
}

User

The merchant account: check-in, settings, KYC/2FA status and sub-users.

PATCH /v1/user/checkin Check in (create or sync merchant record)

Creates Nexus's merchant record for the calling account the first time it is called. Every later call syncs the account with the exchange: newly available deposit currencies are added to the currency settings, confirmation settings are refreshed, fee groups are updated and expired payments are marked. The Nexus dashboard calls this on sign-in. A server-only integration should call it once before anything else, because most other endpoints return User not found until the record exists. Returns 403 if the merchant record is disabled.

Endpoint: PATCH https://YOUR_NEXUS_HOST/v1/user/checkin

Code Examples

curl -X PATCH 'https://YOUR_NEXUS_HOST/v1/user/checkin' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/user/checkin"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.patch(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/user/checkin", {
  method: "PATCH",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "success": true,
  "message": null
}
GET /v1/user/settings Get merchant settings

Return the merchant's currency settings, widget settings, label and account-level switches.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/user/settings

Response

FieldTypeDescription
currency_settings[] array One entry per currency and network: enabled, currency_id, network, is_converted (auto-conversion to the preferred currency), required_confirmations, is_preferred, type, currency_metadata.
widget_settings string The JSON string saved with Update widget settings.
label string Merchant label.
passthrough_fees boolean Deposit default: when true, invoice fees are not added to the amount the customer pays.
payout_passthrough_fees boolean Payout default. See Payout.
overpayment_conversion boolean Whether overpayments are converted to the preferred currency.
skip_payout_mfa boolean Whether payout approval skips the 2FA code. See Payout.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/user/settings' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/user/settings"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/user/settings", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "success": true,
  "message": "",
  "currency_settings": [
    {
      "enabled": true,
      "currency_id": "ETH",
      "network": "SEPOLIA",
      "is_converted": false,
      "required_confirmations": 3,
      "is_preferred": false,
      "type": "Crypto",
      "currency_metadata": null
    }
  ],
  "widget_settings": null,
  "label": "Acme",
  "passthrough_fees": false,
  "payout_passthrough_fees": false,
  "overpayment_conversion": false,
  "skip_payout_mfa": true
}
GET /v1/user/info Get KYC and 2FA status

Return whether the merchant's exchange account has approved KYC and has 2FA enabled.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/user/info

Response

FieldTypeDescription
is_kyc_approved boolean KYC approved on the exchange.
is_mfa_enabled boolean 2FA enabled on the exchange.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/user/info' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/user/info"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/user/info", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "is_kyc_approved": true,
  "is_mfa_enabled": true
}
GET /v1/user/child-users List sub-users

Return the sub-users (child merchants) of the calling merchant, with filters and pagination.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/user/child-users

Query parameters

NameTypeRequiredDescription
showInactive boolean required Include disabled sub-users. Required; the request is rejected without it.
groupName string optional Only sub-users in this fee group.
preferredCurrency string optional Only sub-users with this preferred currency.
search string optional Text search.
pageIndex number optional 1-based page number (default 1). 0 is treated as 1.
pageSize number optional Items per page (default 10).

Response

FieldTypeDescription
results[] array Sub-users: id, sub, parent_user_sub, exchange_id, preferred_currency_id, widget_settings, parent_fee_group_name, email, label, enabled.
total_count / page / size number Paging information.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/user/child-users?showInactive=false&pageIndex=1&pageSize=10' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/user/child-users?showInactive=false&pageIndex=1&pageSize=10"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/user/child-users?showInactive=false&pageIndex=1&pageSize=10", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "results": [
    {
      "id": "3b9d6c1e-2f4a-4c8b-9e7d-5a1f0c2b8d46",
      "sub": "c41f8a2e-7b3d-4e19-a6c5-0d9e2f1b7a34",
      "parent_user_sub": "ec43ce90-8bd8-461d-8c00-df3b90d0b6cf",
      "exchange_id": "your-exchange",
      "preferred_currency_id": "USD",
      "widget_settings": null,
      "parent_fee_group_name": "standard",
      "email": "ops@example.com",
      "label": "Ops team",
      "enabled": true
    }
  ],
  "total_count": 1,
  "page": 1,
  "size": 10
}
POST /v1/user/child Create a sub-user

Create a sub-user under the calling merchant and assign it to one of the merchant's Child fee groups. Fails if the label is already used by one of your sub-users, if the email already exists on the exchange, or if the fee group isn't a Child group you own.

Endpoint: POST https://YOUR_NEXUS_HOST/v1/user/child

Request body

NameTypeRequiredDescription
email string required Sub-user email. Must be a valid address that doesn't already exist on the exchange.
label string required Display label, up to 36 characters. Must be unique among your sub-users.
fee_group_name string required Name of one of your Child fee groups (see Fee).
preferred_currency_id string optional Preferred currency. Defaults to the exchange's default preferred currency.

Response

FieldTypeDescription
user_id string (uuid) Id of the new sub-user. Use it in the Fee group calls.

Code Examples

curl -X POST 'https://YOUR_NEXUS_HOST/v1/user/child' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"email":"ops@example.com","label":"Ops team","fee_group_name":"standard","preferred_currency_id":"USD"}'
import requests

url = "https://YOUR_NEXUS_HOST/v1/user/child"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
}
body = {
    "email": "ops@example.com",
    "label": "Ops team",
    "fee_group_name": "standard",
    "preferred_currency_id": "USD"
}

response = requests.post(url, json=body, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/user/child", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "email": "ops@example.com",
  "label": "Ops team",
  "fee_group_name": "standard",
  "preferred_currency_id": "USD"
}),
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "success": true,
  "message": "",
  "user_id": "3b9d6c1e-2f4a-4c8b-9e7d-5a1f0c2b8d46"
}
PUT /v1/user/child/{id} Enable or disable a sub-user

Switch one of your sub-users between enabled and disabled. There is no request body, and each call flips the current state. Returns 404 if the user doesn't exist and 403 if it isn't your sub-user.

Endpoint: PUT https://YOUR_NEXUS_HOST/v1/user/child/{id}

Path parameters

NameTypeRequiredDescription
id string (uuid) required Sub-user id (the user_id from Create a sub-user).

Code Examples

curl -X PUT 'https://YOUR_NEXUS_HOST/v1/user/child/3b9d6c1e-2f4a-4c8b-9e7d-5a1f0c2b8d46' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/user/child/3b9d6c1e-2f4a-4c8b-9e7d-5a1f0c2b8d46"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.put(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/user/child/3b9d6c1e-2f4a-4c8b-9e7d-5a1f0c2b8d46", {
  method: "PUT",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "success": true,
  "message": null
}
POST /v1/user/logo Upload a logo

Upload a logo image for the payment widget and get back its public URL. Send it as multipart/form-data with a logo file field. Only .png and .svg files smaller than 2 MiB (2,097,152 bytes) are accepted. Anything else returns Invalid extension or exceeded max file size.

Endpoint: POST https://YOUR_NEXUS_HOST/v1/user/logo

Response

FieldTypeDescription
url string Public URL of the uploaded file.

Code Examples

curl -X POST 'https://YOUR_NEXUS_HOST/v1/user/logo' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/user/logo"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.post(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/user/logo", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);
PATCH /v1/user/widget-settings Update widget settings

Save the widget configuration. The value is stored and returned as an opaque string.

Endpoint: PATCH https://YOUR_NEXUS_HOST/v1/user/widget-settings

Request body

NameTypeRequiredDescription
widget_settings string required Widget configuration, typically a JSON-encoded string.

Code Examples

curl -X PATCH 'https://YOUR_NEXUS_HOST/v1/user/widget-settings' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"widget_settings":"{\"theme\":\"light\"}"}'
import requests

url = "https://YOUR_NEXUS_HOST/v1/user/widget-settings"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
}
body = {
    "widget_settings": "{\"theme\":\"light\"}"
}

response = requests.patch(url, json=body, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/user/widget-settings", {
  method: "PATCH",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "widget_settings": "{\"theme\":\"light\"}"
}),
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "success": true,
  "message": null
}
PATCH /v1/user/update-currency-settings Update currency settings

Enable or disable deposit currencies and set auto-conversion per currency and network. Every pair you send must exist for the merchant. Otherwise the call fails with Some of provided currencies are not existed/configured, returned as plain text.

Endpoint: PATCH https://YOUR_NEXUS_HOST/v1/user/update-currency-settings

Request body

NameTypeRequiredDescription
currency_settings[] array required List of settings.
currency_settings[].currency_id string required Currency id.
currency_settings[].network string required Network. The key must be present but can be an empty string.
currency_settings[].is_converted boolean required Auto-convert to the preferred currency.
currency_settings[].enabled boolean required Accept this currency.

Code Examples

curl -X PATCH 'https://YOUR_NEXUS_HOST/v1/user/update-currency-settings' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"currency_settings":[{"currency_id":"ETH","network":"SEPOLIA","is_converted":false,"enabled":true}]}'
import requests

url = "https://YOUR_NEXUS_HOST/v1/user/update-currency-settings"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
}
body = {
    "currency_settings": [{"currency_id": "ETH", "network": "SEPOLIA", "is_converted": false, "enabled": true}]
}

response = requests.patch(url, json=body, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/user/update-currency-settings", {
  method: "PATCH",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "currency_settings": [{"currency_id": "ETH", "network": "SEPOLIA", "is_converted": false, "enabled": true}]
}),
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "success": true,
  "message": null
}
PATCH /v1/user/update-preferred-currency Update preferred currency

Set the merchant's preferred currency, which is the conversion target. Returns 404 with the plain-text body Provided currency does not exist. if the currency isn't available.

Endpoint: PATCH https://YOUR_NEXUS_HOST/v1/user/update-preferred-currency

Request body

NameTypeRequiredDescription
currency_id string required Currency id.

Code Examples

curl -X PATCH 'https://YOUR_NEXUS_HOST/v1/user/update-preferred-currency' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"currency_id":"USD"}'
import requests

url = "https://YOUR_NEXUS_HOST/v1/user/update-preferred-currency"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
}
body = {
    "currency_id": "USD"
}

response = requests.patch(url, json=body, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/user/update-preferred-currency", {
  method: "PATCH",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "currency_id": "USD"
}),
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "success": true,
  "message": null
}
PATCH /v1/user/update-crypto-confirmations Update confirmation counts

Set the number of block confirmations per crypto currency and network at which a deposit counts as client-completed (ClientCompleted). Every pair must exist and be a crypto currency. Otherwise you get a plain-text error: Some of provided currencies are not existed/configured or Some of provided currencies are not crypto.

Endpoint: PATCH https://YOUR_NEXUS_HOST/v1/user/update-crypto-confirmations

Request body

NameTypeRequiredDescription
crypto_confirmation_settings[] array required List of settings.
crypto_confirmation_settings[].currency_id string required Currency id.
crypto_confirmation_settings[].network string required Network.
crypto_confirmation_settings[].confirmations number required Number of confirmations.

Code Examples

curl -X PATCH 'https://YOUR_NEXUS_HOST/v1/user/update-crypto-confirmations' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"crypto_confirmation_settings":[{"currency_id":"ETH","network":"SEPOLIA","confirmations":2}]}'
import requests

url = "https://YOUR_NEXUS_HOST/v1/user/update-crypto-confirmations"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
}
body = {
    "crypto_confirmation_settings": [{"currency_id": "ETH", "network": "SEPOLIA", "confirmations": 2}]
}

response = requests.patch(url, json=body, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/user/update-crypto-confirmations", {
  method: "PATCH",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "crypto_confirmation_settings": [{"currency_id": "ETH", "network": "SEPOLIA", "confirmations": 2}]
}),
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "success": true,
  "message": null
}
PATCH /v1/user/update-threshold-settings Update underpayment thresholds

Set the underpayment tolerance per currency and network for invoice payments. When an invoice is underpaid by no more than this fraction of the amount paid, it completes as CompletedLoss instead of staying partially paid. The value is used as a fraction: the default is 0.01, meaning 1%. Every pair must exist for the merchant.

Endpoint: PATCH https://YOUR_NEXUS_HOST/v1/user/update-threshold-settings

Request body

NameTypeRequiredDescription
threshold_settings[] array required List of settings.
threshold_settings[].currency_id string required Currency id.
threshold_settings[].network string required Network. The key must be present but can be an empty string.
threshold_settings[].threshold_value number optional Tolerance as a fraction, for example 0.01 for 1%. The validator accepts 0 to 100.

Code Examples

curl -X PATCH 'https://YOUR_NEXUS_HOST/v1/user/update-threshold-settings' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"threshold_settings":[{"currency_id":"ETH","network":"SEPOLIA","threshold_value":0.01}]}'
import requests

url = "https://YOUR_NEXUS_HOST/v1/user/update-threshold-settings"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
}
body = {
    "threshold_settings": [{"currency_id": "ETH", "network": "SEPOLIA", "threshold_value": 0.01}]
}

response = requests.patch(url, json=body, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/user/update-threshold-settings", {
  method: "PATCH",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "threshold_settings": [{"currency_id": "ETH", "network": "SEPOLIA", "threshold_value": 0.01}]
}),
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "success": true,
  "message": null
}
PATCH /v1/user/settings/passthrough/{value} Set default deposit fee mode

Set the merchant's default passthrough_fees for new payments. On invoice payments, false adds the merchant and parent fees to the amount the customer must pay, and true leaves the amount as entered. Individual payments can override this. Returns the merchant settings.

Endpoint: PATCH https://YOUR_NEXUS_HOST/v1/user/settings/passthrough/{value}

Path parameters

NameTypeRequiredDescription
value boolean required true or false.

Code Examples

curl -X PATCH 'https://YOUR_NEXUS_HOST/v1/user/settings/passthrough/true' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/user/settings/passthrough/true"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.patch(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/user/settings/passthrough/true", {
  method: "PATCH",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);
PATCH /v1/user/settings/overpayment-conversion/{value} Set overpayment conversion

Turn conversion of overpayments into the preferred currency on or off. Returns the merchant settings.

Endpoint: PATCH https://YOUR_NEXUS_HOST/v1/user/settings/overpayment-conversion/{value}

Path parameters

NameTypeRequiredDescription
value boolean required true or false.

Code Examples

curl -X PATCH 'https://YOUR_NEXUS_HOST/v1/user/settings/overpayment-conversion/false' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/user/settings/overpayment-conversion/false"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.patch(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/user/settings/overpayment-conversion/false", {
  method: "PATCH",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);
PATCH /v1/user/settings/skip-payout-mfa/{value} Set payout 2FA skip (browser only)

Turn the per-approval payout 2FA check off (true) or back on (false). Turning it off requires a valid mfa_code; turning it back on doesn't. Browser only: requests without browser fetch metadata (Sec-Fetch-Site) and an Origin or Referer are rejected with 403, so use the Nexus dashboard for this, not a server. Returns the merchant settings.

Endpoint: PATCH https://YOUR_NEXUS_HOST/v1/user/settings/skip-payout-mfa/{value}

Path parameters

NameTypeRequiredDescription
value boolean required true to skip 2FA on payout approval.

Request body

NameTypeRequiredDescription
mfa_code string optional Current 2FA code. Required when value is true.

Code Examples

curl -X PATCH 'https://YOUR_NEXUS_HOST/v1/user/settings/skip-payout-mfa/{value}' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/user/settings/skip-payout-mfa/{value}"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.patch(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/user/settings/skip-payout-mfa/{value}", {
  method: "PATCH",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Currency

Currencies and networks available to the merchant.

GET /v1/currency List deposit currencies

Return the currencies and networks available for deposits on this merchant.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/currency

Response

FieldTypeDescription
currencies[].currency_id string Currency id.
currencies[].type string Currency type.
currencies[].network string Network. Pass this as currency_network when you create an address.
currencies[].min_confirmations / max_confirmations / block_time number Confirmation bounds and block time in seconds. Each is omitted when not set.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/currency' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/currency"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/currency", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "success": true,
  "message": "",
  "currencies": [
    {
      "currency_id": "ETH",
      "type": "Crypto",
      "network": "SEPOLIA",
      "min_confirmations": 0,
      "max_confirmations": 12,
      "block_time": 15
    }
  ]
}
GET /v1/currency/{currency_id} List currencies convertible with a currency

Return the currencies that have a trading instrument with currency_id on the merchant's exchange, as either base or quote currency.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/currency/{currency_id}

Path parameters

NameTypeRequiredDescription
currency_id string required Currency id.

Response

FieldTypeDescription
currencies[] array Same shape as List deposit currencies.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/currency/USDT' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/currency/USDT"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/currency/USDT", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);
GET /v1/currency/payout List exchange crypto currencies

Return the crypto currencies on the merchant's exchange, one entry per currency id. To build a payout form, use Supported payout routes, which returns the currency and network pairs that are enabled for payouts.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/currency/payout

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/currency/payout' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/currency/payout"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/currency/payout", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Payment

Create and manage invoices and open deposits.

GET /v1/payment List payments

Return the merchant's payments with filters, sorting and pagination.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/payment

Query parameters

NameTypeRequiredDescription
currency string optional Order currency.
status string optional Payment status, as a display name (for example Client Completed) or a code name (for example ClientCompleted).
startDate / endDate string (ISO 8601) optional Filter on creation time (inclusive, UTC).
search string optional Exact payment id, or a case-insensitive partial match on merchant_order_id or the merchant label.
sortBy string optional CreatedAt (default), MerchantsName, OrderId, InvoiceId, InvoiceType, InvoiceAmount, EarnedFee, ExpirationDate, Status, KytStatus, UpdatedAt.
sortDirection string optional Descending (default) or Ascending.
pageIndex number optional 1-based page number (default 1). 0 is treated as 1.
pageSize number optional Items per page (default 10).

Response

FieldTypeDescription
results[] array Payment objects (see Get payment).
total_count / page / size number Paging information.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/payment?pageIndex=1&pageSize=10' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/payment?pageIndex=1&pageSize=10"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/payment?pageIndex=1&pageSize=10", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "results": [
    {
      "id": "a427fc2a-be6b-44b4-9ebb-f0041496be70",
      "owner_user_id": "674016eb-a47f-4c56-9a09-12fd0bccba4a",
      "status": "New",
      "kyt_status": null,
      "currency_id": "ETH",
      "expiration": 86400,
      "target_currency_amount_required": 0.05,
      "target_currency_amount_paid": null,
      "merchant_label": null,
      "merchant_order_id": "order-0001",
      "merchant_order_metadata": {
        "customer": "alice@example.com"
      },
      "merchant_order_description": null,
      "own_merchant_fee": 0,
      "type": "Invoice",
      "pricing_mode": "Convert On Arrival",
      "fees_in_price": true,
      "passthrough_fees": true,
      "created": "2026-11-06T09:00:14.291904+00:00",
      "updated": "2026-11-06T09:00:14.291904+00:00",
      "expired": null
    }
  ],
  "total_count": 1,
  "page": 1,
  "size": 10
}
POST /v1/payment Create a payment

Create an invoice (a fixed amount in an order currency) or an openDeposit (accepts any amount, any number of times). The merchant's currency settings at this moment are stored with the payment, and only those currency and network pairs can be used for its addresses. Returns 403 with an empty body if the account's KYC isn't approved (unless the exchange allows payments without KYC), or if the API key lacks the permission to create this payment type.

Endpoint: POST https://YOUR_NEXUS_HOST/v1/payment

Request body

NameTypeRequiredDescription
type string required invoice or openDeposit (case-insensitive; the display names Invoice / Open Deposit also work).
pricing_mode string required longLivedQuote or convertOnArrival.
amount_required number optional invoice only, and required there. Must be greater than 0, with no more decimals than the order currency's precision. Leave it out for openDeposit; 0 is rejected.
merchant_order_currency_id string optional invoice only, and required there. Must be a currency enabled in the merchant's settings. Ignored for openDeposit.
merchant_order_id string optional Your reference, up to 36 characters. It is echoed in deposit webhooks.
merchant_order_metadata any JSON optional Any JSON value (object, string and so on). It is stored and echoed back unchanged.
merchant_order_description string optional Free-text description.
expiration string (duration) optional Lifetime, as d.hh:mm:ss or hh:mm:ss, from 1 hour to 900 days, for example "1.00:00:00". Leave it out for a payment that never expires.
fees_in_price boolean optional Default true.
passthrough_fees boolean optional Overrides the merchant's passthrough_fees setting.

Response

FieldTypeDescription
payment object The payment object (see Get payment).

Code Examples

curl -X POST 'https://YOUR_NEXUS_HOST/v1/payment' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"type":"invoice","pricing_mode":"convertOnArrival","amount_required":0.05,"merchant_order_currency_id":"ETH","merchant_order_id":"order-0001","merchant_order_metadata":{"customer":"alice@example.com"},"expiration":"1.00:00:00"}'
import requests

url = "https://YOUR_NEXUS_HOST/v1/payment"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
}
body = {
    "type": "invoice",
    "pricing_mode": "convertOnArrival",
    "amount_required": 0.05,
    "merchant_order_currency_id": "ETH",
    "merchant_order_id": "order-0001",
    "merchant_order_metadata": {"customer": "alice@example.com"},
    "expiration": "1.00:00:00"
}

response = requests.post(url, json=body, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/payment", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "type": "invoice",
  "pricing_mode": "convertOnArrival",
  "amount_required": 0.05,
  "merchant_order_currency_id": "ETH",
  "merchant_order_id": "order-0001",
  "merchant_order_metadata": {"customer": "alice@example.com"},
  "expiration": "1.00:00:00"
}),
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "payment": {
    "id": "a427fc2a-be6b-44b4-9ebb-f0041496be70",
    "owner_user_id": "674016eb-a47f-4c56-9a09-12fd0bccba4a",
    "status": "New",
    "kyt_status": null,
    "currency_id": "ETH",
    "expiration": 86400,
    "target_currency_amount_required": 0.05,
    "target_currency_amount_paid": null,
    "merchant_label": null,
    "merchant_order_id": "order-0001",
    "merchant_order_metadata": {
      "customer": "alice@example.com"
    },
    "merchant_order_description": null,
    "own_merchant_fee": 0,
    "type": "Invoice",
    "pricing_mode": "Convert On Arrival",
    "fees_in_price": true,
    "passthrough_fees": true,
    "created": "2026-11-06T09:00:14.291904+00:00",
    "updated": "2026-11-06T09:00:14.291904+00:00",
    "expired": null
  },
  "success": true,
  "message": ""
}
GET /v1/payment/{id} Get payment

Return one of the merchant's payments.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/payment/{id}

Path parameters

NameTypeRequiredDescription
id string (uuid) required Payment id.

Response

FieldTypeDescription
id string (uuid) Payment id.
owner_user_id string Owner merchant.
status string Payment status, as a display name: New, Pending, Processing, Client Partially Completed, Partially Completed, Client Completed, Completed, Completed Loss, Completed Profit, Manual Completed, Manual Rejected, Expired.
kyt_status string | null Pending, Approved, Partially KYT Rejected, Rejected, or null.
currency_id string | null Order currency. null for openDeposit.
expiration number | null Expiration in seconds from creation, or null if the payment never expires.
target_currency_amount_required / target_currency_amount_paid number | null Required and paid amounts in the order currency. On an invoice without passthrough, the required amount includes the merchant and parent fees. null for openDeposit.
merchant_order_id / merchant_order_metadata / merchant_order_description As sent at creation.
own_merchant_fee number | null Merchant fee on the invoice.
type / pricing_mode string Invoice / Open Deposit; Long Lived Quote / Convert On Arrival.
fees_in_price / passthrough_fees boolean As set at creation.
created / updated / expired string (ISO 8601) Timestamps. expired is null unless the payment expired.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/payment/a427fc2a-be6b-44b4-9ebb-f0041496be70' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/payment/a427fc2a-be6b-44b4-9ebb-f0041496be70"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/payment/a427fc2a-be6b-44b4-9ebb-f0041496be70", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "id": "a427fc2a-be6b-44b4-9ebb-f0041496be70",
  "owner_user_id": "674016eb-a47f-4c56-9a09-12fd0bccba4a",
  "status": "New",
  "kyt_status": null,
  "currency_id": "ETH",
  "expiration": 86400,
  "target_currency_amount_required": 0.05,
  "target_currency_amount_paid": null,
  "merchant_label": null,
  "merchant_order_id": "order-0001",
  "merchant_order_metadata": {
    "customer": "alice@example.com"
  },
  "merchant_order_description": null,
  "own_merchant_fee": 0,
  "type": "Invoice",
  "pricing_mode": "Convert On Arrival",
  "fees_in_price": true,
  "passthrough_fees": true,
  "created": "2026-11-06T09:00:14.291904+00:00",
  "updated": "2026-11-06T09:00:14.291904+00:00",
  "expired": null
}
GET /v1/payment/{paymentId}/addresses List a payment's addresses

Return the addresses that have already been created for a payment, each with the transactions detected on it. This call does not create addresses. To create one, use POST /v1/client/address. Available to the payment's owner and the owner's parent merchants.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/payment/{paymentId}/addresses

Path parameters

NameTypeRequiredDescription
paymentId string (uuid) required Payment id.

Response

FieldTypeDescription
addresses[].id / crypto_address / network / address_currency_id / tag_type / tag_value Address details.
addresses[].transactions[] array Transactions detected on the address.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/payment/a427fc2a-be6b-44b4-9ebb-f0041496be70/addresses' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/payment/a427fc2a-be6b-44b4-9ebb-f0041496be70/addresses"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/payment/a427fc2a-be6b-44b4-9ebb-f0041496be70/addresses", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);
GET /v1/payment/export Export payments (Excel)

Download the merchant's payments as an Excel file (.xlsx, sent as application/octet-stream). Accepts the same filters as List payments: currency, status, startDate, endDate and search. Returns No data to generate report when nothing matches.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/payment/export

Query parameters

NameTypeRequiredDescription
currency / status / startDate / endDate / search optional As in List payments.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/payment/export?startDate=2026-11-01&endDate=2026-11-06' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/payment/export?startDate=2026-11-01&endDate=2026-11-06"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/payment/export?startDate=2026-11-01&endDate=2026-11-06", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);
PATCH /v1/payment/{paymentId}/{paymentStatus} Set payment status manually

Set one of your payments to Manual Completed (Complete) or Manual Rejected (Reject), and send a payment webhook delivery. After Reject, later deposits to the payment's addresses are still recorded and reported as transaction deliveries, but they are not converted. Complete does not change how later deposits are processed. Returns 404 Payment not found. for an id you don't own.

Endpoint: PATCH https://YOUR_NEXUS_HOST/v1/payment/{paymentId}/{paymentStatus}

Path parameters

NameTypeRequiredDescription
paymentId string (uuid) required Payment id.
paymentStatus string required Complete or Reject.

Response

FieldTypeDescription
(payment object) object See Get payment.

Code Examples

curl -X PATCH 'https://YOUR_NEXUS_HOST/v1/payment/a427fc2a-be6b-44b4-9ebb-f0041496be70/Complete' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/payment/a427fc2a-be6b-44b4-9ebb-f0041496be70/Complete"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.patch(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/payment/a427fc2a-be6b-44b4-9ebb-f0041496be70/Complete", {
  method: "PATCH",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Client (public)

Endpoints for the paying customer's side. No Bearer token is needed; the payment id identifies the payment.

POST /v1/client/address Get or create a payment address

Return the address for a payment and a currency/network pair, creating it on first use. Repeated calls with the same payment and pair return the same address. The currency is chosen as follows: for openDeposit payments and convertOnArrival invoices, the currency you send is used. For longLivedQuote invoices, the order currency is used, unless you pass a quote_id obtained from POST /v1/client/quote, in which case the quote's source currency and network are used. The pair must be in the payment's currency snapshot. Public: this endpoint needs no Bearer token, and the payment id acts as the credential.

Endpoint: POST https://YOUR_NEXUS_HOST/v1/client/address

Request body

NameTypeRequiredDescription
payment_id string (uuid) required Payment id.
currency string optional Currency id. Used for openDeposit and convertOnArrival.
currency_network string optional Network. Converted to upper case. For invoices, defaults to the order currency's network.
quote_id string (uuid) optional Quote id, for longLivedQuote invoices.

Response

FieldTypeDescription
address_id string (uuid) Address id.
address string On-chain address.
address_currency_id / address_currency_network string Pair the address belongs to.
tag_type / tag_value string | null Memo or tag, on chains that need one.

Code Examples

curl -X POST 'https://YOUR_NEXUS_HOST/v1/client/address' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"payment_id":"a427fc2a-be6b-44b4-9ebb-f0041496be70","currency":"ETH","currency_network":"SEPOLIA"}'
import requests

url = "https://YOUR_NEXUS_HOST/v1/client/address"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
}
body = {
    "payment_id": "a427fc2a-be6b-44b4-9ebb-f0041496be70",
    "currency": "ETH",
    "currency_network": "SEPOLIA"
}

response = requests.post(url, json=body, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/client/address", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "payment_id": "a427fc2a-be6b-44b4-9ebb-f0041496be70",
  "currency": "ETH",
  "currency_network": "SEPOLIA"
}),
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "address_id": "a1ff35ed-276f-4db4-9b35-01f28b97338a",
  "address": "0xbC0B3C687496aB9D053b09BFcAfA05C184072aA4",
  "address_currency_id": "ETH",
  "address_currency_network": "SEPOLIA",
  "tag_type": null,
  "tag_value": null,
  "success": true,
  "message": ""
}
GET /v1/client/payment/{id} Get payment status (public)

Return a payment's public view, including its status and detected transactions. Public: no Bearer token needed. Returns 404 The payment does not exist. or 400 Payment with id: [{id}] is expired.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/client/payment/{id}

Path parameters

NameTypeRequiredDescription
id string (uuid) required Payment id.

Response

FieldTypeDescription
payment.client_status string Payment status.
payment.* Also: id, currency_id, currency_network, target_currency_amount_required, target_currency_amount_paid, target_currency_amount_left, fee amounts, expiration, type, pricing_mode, currency_settings, passthrough_fees and more.
transactions[] array Transactions detected so far.
widget_setting / widget_languages Widget data.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/client/payment/a427fc2a-be6b-44b4-9ebb-f0041496be70' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/client/payment/a427fc2a-be6b-44b4-9ebb-f0041496be70"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/client/payment/a427fc2a-be6b-44b4-9ebb-f0041496be70", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Payout

Send settled funds to external addresses. A payout is created (Pending), then approved, which debits the balance and sends it on chain, and is finally completed or rejected. Every change is pushed to your webhook as a payout.* event. Payouts use the same host, Bearer token and webhook as payments.

Payout security settings

2FA on approval. By default, Approve a payout needs the merchant user's current 2FA code. For server-to-server integrations, a merchant user turns on skip_payout_mfa once, from the merchant dashboard. This needs a valid 2FA code, and the setting cannot be changed through the API. After that, approvals need no body, and creating payouts no longer requires 2FA to be enabled on the exchange account. The current value is returned by GET /v1/user/settings as skip_payout_mfa.

IP whitelist. Up to 10 IPs or CIDR ranges (minimum /16 for IPv4, /48 for IPv6) can be managed under /v1/user/settings/whitelisted-ips (GET, POST { "ip_address", "label" }, PUT /{id}, DELETE /{id}). Once the list is non-empty, Create and Approve from any other IP return 403 with Request IP address is not whitelisted.. An empty list means no restriction.

Status model

Stageapproval_statusexecution_statusWebhook event
CreatedPendingNewpayout.initiated
Approved, being sent (can repeat)ApprovedProcessingpayout.processing
Confirmed on chainApprovedCompletedpayout.completed
Rejected by the exchange (fees refunded)ApprovedRejectedpayout.rejected
Rejected by you while pendingRejectedNewpayout.rejected

Payout webhook events

Payout events are delivered to every enabled webhook, in an envelope: event is one of payout.initiated, payout.processing, payout.completed or payout.rejected, and data.status repeats it. data.amount is the gross amount. To get fees and the net amount, call Get payout by id. Signatures work the same way as for every other delivery; see Register a webhook.

{
  "event": "payout.completed",
  "data": {
    "payout_id": "6f1d2c3b-8a47-4e0f-9b52-0c7e1a9d4f21",
    "blockchain_transaction_hash": "0x2887de8e5ce88810f7501b24af05a9abdd10c03ad6dc4ce97e86306af1f4fb28",
    "status": "payout.completed",
    "amount": 0.01,
    "destination_address": "0x4e83362442B8d1bec281594CEa3050C8eB01311C",
    "exchange_payment_id": "019dd623-f9fb-72ab-9163-03d8d87dd90e",
    "note": "INT_CLIENT_0000001:WD-000123",
    "currency": "ETH",
    "timestamp": "2026-11-06T10:16:41.0087312Z",
    "kyt": null
  }
}
POST /v1/payout Create a payout

Create a crypto payout to an external address. The request is validated (account KYC/2FA prerequisites, enabled route, address validity for the network, minimum amount after fees) and the fees are quoted. The payout is recorded as Pending / New, and no funds move until you approve it. Fires payout.initiated. Subject to the payout IP whitelist.

Endpoint: POST https://YOUR_NEXUS_HOST/v1/payout

Request body

NameTypeRequiredDescription
currency_id string required Currency to send, e.g. "ETH", "USDT". Upper-cased.
network string required Network as returned by Supported payout routes (crypto_network), e.g. "SEPOLIA", "TRC20". Upper-cased.
amount number required Gross amount in the source currency. Must be greater than 0. After fees it must still be at or above payout_minimal_amount.
destination_address string required Recipient address. Validated against the network.
destination_address_tag_type string optional Tag type for routes that need a memo or destination tag.
destination_address_tag_value string optional Memo or destination tag value.
note string optional Free text, up to 256 characters. It is echoed in webhooks and can be searched in List payouts.
passthrough_fees boolean optional true: the recipient gets exactly amount and your account covers the fees. false: fees are deducted from amount. Defaults to your payout_passthrough_fees setting.

Response

FieldTypeDescription
id string (uuid) Payout id. Use it in every other payout call. Webhooks carry it as payout_id.
currency string Asset being sent.
network string Chain the payout is sent on (upper case).
amount number Gross amount requested at creation.
fee number Exchange network/withdrawal fee. Estimated at creation, replaced by the actual fee at approval.
parent_merchant_fee number Fee charged by the parent merchant, if any.
own_merchant_fee number Your own payout fee from your default fee group, if any.
final_amount number What the recipient receives: amount when passthrough is on, otherwise amount - fee - parent_merchant_fee - own_merchant_fee.
destination_address string Recipient address.
tag_type / tag_value string | null Destination memo or tag, if one was sent.
exchange_payment_id string | null Exchange-side payment id. Populated at approval.
blockchain_hash string | null On-chain transaction hash, once known.
note string | null Your free-text reference from creation.
approval_status string Pending, Approved or Rejected.
execution_status string New, Processing, Completed or Rejected.
created_at / updated_at string (ISO 8601, UTC) Timestamps.
kyt object | null KYT screening result when screening is enabled: kytStatus (Pending, Approved or Rejected), riscScore, decisionReason, errorMessage, analysedAt.
payout_passthrough_fees boolean Whether fees were kept out of amount for this payout.
is_refund / manual_refund boolean / object | null Set when the payout was created by a manual refund. false / null for API-created payouts.

Code Examples

curl -X POST 'https://YOUR_NEXUS_HOST/v1/payout' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"currency_id":"ETH","network":"SEPOLIA","amount":0.01,"destination_address":"0x4e83362442B8d1bec281594CEa3050C8eB01311C","note":"INT_CLIENT_0000001:WD-000123","passthrough_fees":false}'
import requests

url = "https://YOUR_NEXUS_HOST/v1/payout"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
}
body = {
    "currency_id": "ETH",
    "network": "SEPOLIA",
    "amount": 0.01,
    "destination_address": "0x4e83362442B8d1bec281594CEa3050C8eB01311C",
    "note": "INT_CLIENT_0000001:WD-000123",
    "passthrough_fees": False
}

response = requests.post(url, json=body, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/payout", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "currency_id": "ETH",
  "network": "SEPOLIA",
  "amount": 0.01,
  "destination_address": "0x4e83362442B8d1bec281594CEa3050C8eB01311C",
  "note": "INT_CLIENT_0000001:WD-000123",
  "passthrough_fees": false
}),
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "id": "6f1d2c3b-8a47-4e0f-9b52-0c7e1a9d4f21",
  "currency": "ETH",
  "network": "SEPOLIA",
  "amount": 0.01,
  "fee": 0.0002,
  "parent_merchant_fee": 0,
  "own_merchant_fee": 0,
  "final_amount": 0.0098,
  "destination_address": "0x4e83362442B8d1bec281594CEa3050C8eB01311C",
  "tag_type": null,
  "tag_value": null,
  "exchange_payment_id": null,
  "blockchain_hash": null,
  "note": "INT_CLIENT_0000001:WD-000123",
  "approval_status": "Pending",
  "execution_status": "New",
  "created_at": "2026-11-06T10:15:02.184Z",
  "updated_at": "2026-11-06T10:15:02.184Z",
  "kyt": null,
  "payout_passthrough_fees": false,
  "is_refund": false,
  "manual_refund": null
}
PATCH /v1/payout/{payoutId}/approve Approve a payout

Approve a Pending payout and send it to the exchange for on-chain execution. This checks free_balance against amount, books the payout fees, and moves the payout to Approved / Processing, filling in exchange_payment_id and the actual fee. Fires payout.processing. A payout can be approved only once. If approval fails, the payout stays Pending. The body is optional: mfa_code is only required when the merchant's skip_payout_mfa setting is off. Subject to the payout IP whitelist.

Endpoint: PATCH https://YOUR_NEXUS_HOST/v1/payout/{payoutId}/approve

Path parameters

NameTypeRequiredDescription
payoutId string (uuid) required The id returned by Create a payout.

Request body

NameTypeRequiredDescription
mfa_code string optional Current 6-digit 2FA code of the merchant user. Required only when skip_payout_mfa is false.
wallet_id string optional Exchange wallet to debit, when the account has more than one. Leave it out to use the default wallet.

Response

FieldTypeDescription
(payout object) object Same shape as Create a payout.

Code Examples

curl -X PATCH 'https://YOUR_NEXUS_HOST/v1/payout/6f1d2c3b-8a47-4e0f-9b52-0c7e1a9d4f21/approve' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/payout/6f1d2c3b-8a47-4e0f-9b52-0c7e1a9d4f21/approve"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.patch(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/payout/6f1d2c3b-8a47-4e0f-9b52-0c7e1a9d4f21/approve", {
  method: "PATCH",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "id": "6f1d2c3b-8a47-4e0f-9b52-0c7e1a9d4f21",
  "currency": "ETH",
  "network": "SEPOLIA",
  "amount": 0.01,
  "fee": 0.000029,
  "parent_merchant_fee": 0,
  "own_merchant_fee": 0,
  "final_amount": 0.009971,
  "destination_address": "0x4e83362442B8d1bec281594CEa3050C8eB01311C",
  "tag_type": null,
  "tag_value": null,
  "exchange_payment_id": "019dd623-f9fb-72ab-9163-03d8d87dd90e",
  "blockchain_hash": null,
  "note": "INT_CLIENT_0000001:WD-000123",
  "approval_status": "Approved",
  "execution_status": "Processing",
  "created_at": "2026-11-06T10:15:02.184Z",
  "updated_at": "2026-11-06T10:15:03.902Z",
  "kyt": null,
  "payout_passthrough_fees": false,
  "is_refund": false,
  "manual_refund": null
}
PATCH /v1/payout/{payoutId}/reject Reject a payout

Cancel a Pending payout. The record is kept for audit, approval_status becomes Rejected, and no funds move. Fires payout.rejected. A payout that has already been approved cannot be rejected.

Endpoint: PATCH https://YOUR_NEXUS_HOST/v1/payout/{payoutId}/reject

Path parameters

NameTypeRequiredDescription
payoutId string (uuid) required The id returned by Create a payout.

Response

FieldTypeDescription
(payout object) object Same shape as Create a payout.

Code Examples

curl -X PATCH 'https://YOUR_NEXUS_HOST/v1/payout/6f1d2c3b-8a47-4e0f-9b52-0c7e1a9d4f21/reject' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/payout/6f1d2c3b-8a47-4e0f-9b52-0c7e1a9d4f21/reject"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.patch(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/payout/6f1d2c3b-8a47-4e0f-9b52-0c7e1a9d4f21/reject", {
  method: "PATCH",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "id": "6f1d2c3b-8a47-4e0f-9b52-0c7e1a9d4f21",
  "currency": "ETH",
  "network": "SEPOLIA",
  "amount": 0.01,
  "fee": 0.0002,
  "parent_merchant_fee": 0,
  "own_merchant_fee": 0,
  "final_amount": 0.0098,
  "destination_address": "0x4e83362442B8d1bec281594CEa3050C8eB01311C",
  "tag_type": null,
  "tag_value": null,
  "exchange_payment_id": null,
  "blockchain_hash": null,
  "note": "INT_CLIENT_0000001:WD-000123",
  "approval_status": "Rejected",
  "execution_status": "New",
  "created_at": "2026-11-06T10:15:02.184Z",
  "updated_at": "2026-11-06T10:20:11.530Z",
  "kyt": null,
  "payout_passthrough_fees": false,
  "is_refund": false,
  "manual_refund": null
}
GET /v1/payout/{payoutId} Get payout by id

Look up one payout, with its current approval status, execution status, fees and on-chain hash. Returns 404 Withdrawal not found. if the id does not belong to the caller.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/payout/{payoutId}

Path parameters

NameTypeRequiredDescription
payoutId string (uuid) required The id returned by Create a payout.

Response

FieldTypeDescription
(payout object) object Same shape as Create a payout.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/payout/6f1d2c3b-8a47-4e0f-9b52-0c7e1a9d4f21' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/payout/6f1d2c3b-8a47-4e0f-9b52-0c7e1a9d4f21"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/payout/6f1d2c3b-8a47-4e0f-9b52-0c7e1a9d4f21", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "id": "6f1d2c3b-8a47-4e0f-9b52-0c7e1a9d4f21",
  "currency": "ETH",
  "network": "SEPOLIA",
  "amount": 0.01,
  "fee": 0.000029,
  "parent_merchant_fee": 0,
  "own_merchant_fee": 0,
  "final_amount": 0.009971,
  "destination_address": "0x4e83362442B8d1bec281594CEa3050C8eB01311C",
  "tag_type": null,
  "tag_value": null,
  "exchange_payment_id": "019dd623-f9fb-72ab-9163-03d8d87dd90e",
  "blockchain_hash": "0x2887de8e5ce88810f7501b24af05a9abdd10c03ad6dc4ce97e86306af1f4fb28",
  "note": "INT_CLIENT_0000001:WD-000123",
  "approval_status": "Approved",
  "execution_status": "Completed",
  "created_at": "2026-11-06T10:15:02.184Z",
  "updated_at": "2026-11-06T10:16:41.006Z",
  "kyt": null,
  "payout_passthrough_fees": false,
  "is_refund": false,
  "manual_refund": null
}
GET /v1/payout/list List payouts

Return the merchant's payouts, newest first, with filters and pagination.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/payout/list

Query parameters

NameTypeRequiredDescription
pageIndex number optional 1-based page number (default 1).
pageSize number optional Items per page (default 10).
currency string optional Filter by currency id.
approvalStatus string optional Pending, Approved or Rejected.
executionStatus string optional New, Processing, Completed or Rejected.
startDate / endDate string (ISO 8601) optional Filter on created_at (inclusive, UTC).
search string optional Exact payout id or exchange_payment_id, or any text contained in note.

Response

FieldTypeDescription
results array Payout objects (same shape as Create a payout).
total_count number Total matching payouts.
page / size number Echo of pageIndex / pageSize.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/payout/list?pageIndex=1&pageSize=10&executionStatus=Processing' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/payout/list?pageIndex=1&pageSize=10&executionStatus=Processing"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/payout/list?pageIndex=1&pageSize=10&executionStatus=Processing", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "results": [
    {
      "id": "6f1d2c3b-8a47-4e0f-9b52-0c7e1a9d4f21",
      "currency": "ETH",
      "network": "SEPOLIA",
      "amount": 0.01,
      "fee": 0.000029,
      "parent_merchant_fee": 0,
      "own_merchant_fee": 0,
      "final_amount": 0.009971,
      "destination_address": "0x4e83362442B8d1bec281594CEa3050C8eB01311C",
      "tag_type": null,
      "tag_value": null,
      "exchange_payment_id": "019dd623-f9fb-72ab-9163-03d8d87dd90e",
      "blockchain_hash": null,
      "note": "INT_CLIENT_0000001:WD-000123",
      "approval_status": "Approved",
      "execution_status": "Processing",
      "created_at": "2026-11-06T10:15:02.184Z",
      "updated_at": "2026-11-06T10:15:03.902Z",
      "kyt": null,
      "payout_passthrough_fees": false,
      "is_refund": false,
      "manual_refund": null
    }
  ],
  "total_count": 1,
  "page": 1,
  "size": 10
}
GET /v1/payout/payment-routes Supported payout routes

Return the currency and network pairs enabled for payouts on this merchant. Build payout forms from this list. It can differ from the deposit currency list.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/payout/payment-routes

Response

FieldTypeDescription
payment_routes[].currency string Currency id.
payment_routes[].crypto_network string Network to pass as network on Create a payout.
payment_routes[].crypto_tag_type string Present only when the route needs a destination memo or tag.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/payout/payment-routes' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/payout/payment-routes"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/payout/payment-routes", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "payment_routes": [
    {
      "currency": "ETH",
      "crypto_network": "SEPOLIA"
    },
    {
      "currency": "USDT",
      "crypto_network": "TRC20"
    }
  ]
}
GET /v1/payout/info/{currency_id} Payout balance and limits

Return the merchant's balance, minimum payout amount, remaining periodic payout limits and the total of payouts that are still pending, for one currency.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/payout/info/{currency_id}

Path parameters

NameTypeRequiredDescription
currency_id string required Currency id.

Query parameters

NameTypeRequiredDescription
walletId string optional Exchange wallet to read the balance from. Defaults to the default wallet.

Response

FieldTypeDescription
account_balance.free_balance number Balance available for payouts. Approval checks amount against this figure.
account_balance.total_balance / exposed_balance number Total balance, and the part that is reserved.
payment_limit.payout_minimal_amount number Minimum net payout amount.
payment_limit.payout_daily_limit / payout_weekly_limit / payout_monthly_limit number Remaining payout allowance in the current period.
pending_payouts_amount number Sum of payouts created but not yet finished.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/payout/info/ETH' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/payout/info/ETH"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/payout/info/ETH", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "account_balance": {
    "free_balance": 1.25,
    "total_balance": 1.3,
    "exposed_balance": 0.05
  },
  "payment_limit": {
    "currency": "ETH",
    "payout_minimal_amount": 0.001,
    "payout_daily_limit": 5,
    "payout_weekly_limit": 20,
    "payout_monthly_limit": 50
  },
  "pending_payouts_amount": 0.05
}
GET /v1/payout/fee-estimation/{currency_id}/{network}/{amount} Estimate payout fees

Quote the fees and the recipient amount for a hypothetical payout, using the same calculation as Create a payout. Read only.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/payout/fee-estimation/{currency_id}/{network}/{amount}

Path parameters

NameTypeRequiredDescription
currency_id string required Currency id.
network string required Network, as in Supported payout routes.
amount number required Gross amount. Must be greater than 0.

Query parameters

NameTypeRequiredDescription
passthroughFees boolean optional Preview either fee mode. Defaults to the merchant's payout_passthrough_fees setting.

Response

FieldTypeDescription
fee_estimation number Total of all fees.
final_amount number What the recipient would receive.
fees.exchange_fee / fees.parent_merchant_fee / fees.merchant_fee number Fee breakdown. The exchange fee is an estimate.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/payout/fee-estimation/ETH/SEPOLIA/0.01?passthroughFees=false' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/payout/fee-estimation/ETH/SEPOLIA/0.01?passthroughFees=false"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/payout/fee-estimation/ETH/SEPOLIA/0.01?passthroughFees=false", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "fee_estimation": 0.0002,
  "final_amount": 0.0098,
  "fees": {
    "parent_merchant_fee": 0,
    "merchant_fee": 0,
    "exchange_fee": 0.0002
  }
}
GET /v1/payout/addresses-history Previously used payout addresses

Return the destination addresses this merchant has sent payouts to, most used first. Useful for an address-book style picker.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/payout/addresses-history

Response

FieldTypeDescription
addresses[].destination_address / network / currency string Address and route.
addresses[].address_tag_type / address_tag_value string Present only when a tag was used.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/payout/addresses-history' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/payout/addresses-history"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/payout/addresses-history", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "addresses": [
    {
      "destination_address": "0x4e83362442B8d1bec281594CEa3050C8eB01311C",
      "network": "SEPOLIA",
      "currency": "ETH"
    }
  ]
}
PATCH /v1/user/settings/payout-passthrough/{value} Set default payout fee mode

Set the merchant's default payout_passthrough_fees. With true, recipients get the full amount and your account covers the fees. With false, fees are deducted from amount. Individual payouts can override this with passthrough_fees. Returns the merchant settings.

Endpoint: PATCH https://YOUR_NEXUS_HOST/v1/user/settings/payout-passthrough/{value}

Path parameters

NameTypeRequiredDescription
value boolean required true or false.

Code Examples

curl -X PATCH 'https://YOUR_NEXUS_HOST/v1/user/settings/payout-passthrough/true' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/user/settings/payout-passthrough/true"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.patch(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/user/settings/payout-passthrough/true", {
  method: "PATCH",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Webhook

Register URLs to receive real-time payment and payout events, enable or disable them, or remove them.

GET /v1/webhook List webhooks

Return every webhook the merchant has registered.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/webhook

Response

FieldTypeDescription
web_hooks[] array Webhook objects: id, url, enabled, label, created.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/webhook' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/webhook"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/webhook", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "success": true,
  "message": "",
  "web_hooks": [
    {
      "id": "8f3c27d4-55b1-4c2e-9a7e-1f0b9a3e4d22",
      "url": "https://example.com/webhooks/nexus",
      "enabled": true,
      "label": "Production events",
      "created": "2026-11-06T09:58:12.481Z"
    }
  ]
}
POST /v1/webhook Register a webhook

Register a URL to receive event notifications. A merchant can have up to 5 webhooks. The returned id is also the signing secret for deliveries, so store it safely.

Endpoint: POST https://YOUR_NEXUS_HOST/v1/webhook

Verifying deliveries

Every delivery is a POST with a JSON body and an x-webhook-signature header. The signature is a plain SHA-256 hash, not an HMAC: hex(sha256(webhook_id + raw_body)), lower case, where webhook_id is this webhook's id. There is no separate secret. Treat the id as one. Hash the raw request bytes, not JSON you have parsed and serialised again, and compare in constant time. A non-2xx response or a network error is retried twice, 1 s and then 2 s later (three attempts in total), and then the delivery is dropped. Payment events and payout events go to every enabled webhook.

Request body

NameTypeRequiredDescription
url string required Absolute URL that will receive POST deliveries.
label string optional Human-readable label, up to 200 characters.

Response

FieldTypeDescription
web_hook.id string (uuid) Webhook id. It is also the signing secret.
web_hook.url / label string As registered.
web_hook.enabled boolean Whether deliveries are active.
web_hook.created string Creation timestamp.

Code Examples

curl -X POST 'https://YOUR_NEXUS_HOST/v1/webhook' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"label":"Production events","url":"https://example.com/webhooks/nexus"}'
import requests

url = "https://YOUR_NEXUS_HOST/v1/webhook"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
}
body = {
    "label": "Production events",
    "url": "https://example.com/webhooks/nexus"
}

response = requests.post(url, json=body, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/webhook", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "label": "Production events",
  "url": "https://example.com/webhooks/nexus"
}),
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "success": true,
  "message": "",
  "web_hook": {
    "id": "8f3c27d4-55b1-4c2e-9a7e-1f0b9a3e4d22",
    "url": "https://example.com/webhooks/nexus",
    "enabled": true,
    "label": "Production events",
    "created": "2026-11-06T09:58:12.481Z"
  }
}
PUT /v1/webhook/{webhook_id} Enable or disable a webhook

Switch a webhook between enabled and disabled. There is no request body, and each call flips the current state. The URL and id cannot be changed. To rotate the signing secret, register a new webhook, move your verifier to the new id, then delete the old one.

Endpoint: PUT https://YOUR_NEXUS_HOST/v1/webhook/{webhook_id}

Path parameters

NameTypeRequiredDescription
webhook_id string (uuid) required Webhook id.

Code Examples

curl -X PUT 'https://YOUR_NEXUS_HOST/v1/webhook/8f3c27d4-55b1-4c2e-9a7e-1f0b9a3e4d22' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/webhook/8f3c27d4-55b1-4c2e-9a7e-1f0b9a3e4d22"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.put(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/webhook/8f3c27d4-55b1-4c2e-9a7e-1f0b9a3e4d22", {
  method: "PUT",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "success": true,
  "message": null
}
DELETE /v1/webhook/{webhook_id} Delete a webhook

Remove a webhook. Deliveries to it stop immediately.

Endpoint: DELETE https://YOUR_NEXUS_HOST/v1/webhook/{webhook_id}

Path parameters

NameTypeRequiredDescription
webhook_id string (uuid) required Webhook id.

Code Examples

curl -X DELETE 'https://YOUR_NEXUS_HOST/v1/webhook/8f3c27d4-55b1-4c2e-9a7e-1f0b9a3e4d22' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/webhook/8f3c27d4-55b1-4c2e-9a7e-1f0b9a3e4d22"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.delete(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/webhook/8f3c27d4-55b1-4c2e-9a7e-1f0b9a3e4d22", {
  method: "DELETE",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "success": true,
  "message": null
}

Address Book

The account's saved crypto destination addresses (stored on the exchange).

POST /v1/addressbook Save address-book contacts

Validate each address for its currency and network, then send the list to the exchange as the account's saved crypto addresses (favorite_addresses_crypto on the exchange user). The response is the saved list the exchange returns. If any address is invalid, nothing is saved and you get Invalid address provided for {currency} {network}.

Endpoint: POST https://YOUR_NEXUS_HOST/v1/addressbook

Request body

NameTypeRequiredDescription
address_book_contacts[] array required Contacts.
address_book_contacts[].name string optional Label.
address_book_contacts[].currency string optional Currency id.
address_book_contacts[].network string optional Network.
address_book_contacts[].address string optional Address.
address_book_contacts[].address_tag_type / address_tag_value string optional Memo or tag, if needed.

Code Examples

curl -X POST 'https://YOUR_NEXUS_HOST/v1/addressbook' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"address_book_contacts":[{"name":"Cold storage","currency":"ETH","network":"SEPOLIA","address":"0x4e83362442B8d1bec281594CEa3050C8eB01311C"}]}'
import requests

url = "https://YOUR_NEXUS_HOST/v1/addressbook"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
}
body = {
    "address_book_contacts": [{"name": "Cold storage", "currency": "ETH", "network": "SEPOLIA", "address": "0x4e83362442B8d1bec281594CEa3050C8eB01311C"}]
}

response = requests.post(url, json=body, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/addressbook", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "address_book_contacts": [{"name": "Cold storage", "currency": "ETH", "network": "SEPOLIA", "address": "0x4e83362442B8d1bec281594CEa3050C8eB01311C"}]
}),
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "results": [
    {
      "name": "Cold storage",
      "currency": "ETH",
      "network": "SEPOLIA",
      "address": "0x4e83362442B8d1bec281594CEa3050C8eB01311C"
    }
  ],
  "total_count": 1,
  "page": 1,
  "size": 1
}
GET /v1/addressbook/list List address-book contacts

Return all saved contacts. The endpoint takes no paging parameters; every contact is returned in a single page.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/addressbook/list

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/addressbook/list' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/addressbook/list"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/addressbook/list", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "results": [
    {
      "name": "Cold storage",
      "currency": "ETH",
      "network": "SEPOLIA",
      "address": "0x4e83362442B8d1bec281594CEa3050C8eB01311C"
    }
  ],
  "total_count": 1,
  "page": 1,
  "size": 1
}

Fee

Fee groups set the deposit and payout fees for you and your sub-users. All percentage fees are fractions from 0 to 1.

GET /v1/fee/payment-fees/{paymentId} Fees for a payment

Return the fee records of a payment.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/fee/payment-fees/{paymentId}

Path parameters

NameTypeRequiredDescription
paymentId string (uuid) required Payment id.

Response

FieldTypeDescription
payment_fees[] array Fee records: fee_group_id, payment_id, amount_required, amount_paid, order_currency_amount, currency, fee_status, fail_message.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/fee/payment-fees/a427fc2a-be6b-44b4-9ebb-f0041496be70' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/fee/payment-fees/a427fc2a-be6b-44b4-9ebb-f0041496be70"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/fee/payment-fees/a427fc2a-be6b-44b4-9ebb-f0041496be70", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);
GET /v1/fee/groups List fee groups

Return the merchant's fee groups.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/fee/groups

Query parameters

NameTypeRequiredDescription
type string optional Child (groups for sub-users) or Own.
search string optional Text search.
pageIndex number optional 1-based page number (default 1). 0 is treated as 1.
pageSize number optional Items per page (default 10).

Response

FieldTypeDescription
results[] array Fee groups: id, group_name, is_default, group_type, default_deposit_fee, default_payout_fee, fees (currency_id, deposit_fee, deposit_flat_fee, updated_at, is_custom), payout_fees (currency_id, progressive_fee, flat_fee, updated_at, is_custom), users.
total_count / page / size number Paging information.

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/fee/groups?type=Child&pageIndex=1&pageSize=10' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/fee/groups?type=Child&pageIndex=1&pageSize=10"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/fee/groups?type=Child&pageIndex=1&pageSize=10", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "results": [
    {
      "id": "9c2e7a14-0b3d-4f58-8e61-2d7a9b4c1f03",
      "group_name": "standard",
      "is_default": false,
      "group_type": "Child",
      "default_deposit_fee": 0.01,
      "default_payout_fee": 0.005,
      "fees": [
        {
          "currency_id": "ETH",
          "deposit_fee": 0.008,
          "deposit_flat_fee": null,
          "updated_at": "2026-11-06T09:00:00Z",
          "is_custom": true
        }
      ],
      "payout_fees": [],
      "users": []
    }
  ],
  "total_count": 1,
  "page": 1,
  "size": 10
}
GET /v1/fee/group/{groupName} Get fee group by name

Return one of your fee groups. Returns 404 You do not have fee group with provided name: {name}. if it doesn't exist.

Endpoint: GET https://YOUR_NEXUS_HOST/v1/fee/group/{groupName}

Path parameters

NameTypeRequiredDescription
groupName string required Group name (URL-encoded).

Code Examples

curl -X GET 'https://YOUR_NEXUS_HOST/v1/fee/group/standard' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/fee/group/standard"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.get(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/fee/group/standard", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "id": "9c2e7a14-0b3d-4f58-8e61-2d7a9b4c1f03",
  "group_name": "standard",
  "is_default": false,
  "group_type": "Child",
  "default_deposit_fee": 0.01,
  "default_payout_fee": 0.005,
  "fees": [
    {
      "currency_id": "ETH",
      "deposit_fee": 0.008,
      "deposit_flat_fee": null,
      "updated_at": "2026-11-06T09:00:00Z",
      "is_custom": true
    }
  ],
  "payout_fees": [],
  "users": []
}
POST /v1/fee/group Create a fee group

Create a fee group. Groups created here are always of type Child, meaning they are assigned to sub-users. Returns the new group.

Endpoint: POST https://YOUR_NEXUS_HOST/v1/fee/group

Request body

NameTypeRequiredDescription
name string required Group name.
default_deposit_fee number required Default deposit fee as a fraction from 0 to 1 (0.01 = 1%).
default_payout_fee number optional Default payout fee as a fraction from 0 to 1.
fees[] array optional Per-currency deposit fees: currency_id (required), deposit_fee (fraction from 0 to 1), deposit_flat_fee (at least 0).
payout_fees[] array optional Per-currency payout fees: currency_id (required), progressive_fee (fraction from 0 to 1), flat_fee (at least 0).

Code Examples

curl -X POST 'https://YOUR_NEXUS_HOST/v1/fee/group' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"name":"standard","default_deposit_fee":0.01,"default_payout_fee":0.005,"fees":[{"currency_id":"ETH","deposit_fee":0.008}]}'
import requests

url = "https://YOUR_NEXUS_HOST/v1/fee/group"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
}
body = {
    "name": "standard",
    "default_deposit_fee": 0.01,
    "default_payout_fee": 0.005,
    "fees": [{"currency_id": "ETH", "deposit_fee": 0.008}]
}

response = requests.post(url, json=body, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/fee/group", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "name": "standard",
  "default_deposit_fee": 0.01,
  "default_payout_fee": 0.005,
  "fees": [{"currency_id": "ETH", "deposit_fee": 0.008}]
}),
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "id": "9c2e7a14-0b3d-4f58-8e61-2d7a9b4c1f03",
  "group_name": "standard",
  "is_default": false,
  "group_type": "Child",
  "default_deposit_fee": 0.01,
  "default_payout_fee": 0.005,
  "fees": [
    {
      "currency_id": "ETH",
      "deposit_fee": 0.008,
      "deposit_flat_fee": null,
      "updated_at": "2026-11-06T09:00:00Z",
      "is_custom": true
    }
  ],
  "payout_fees": [],
  "users": []
}
PUT /v1/fee/group Update a fee group

Replace a fee group's rates, and optionally rename it. This is a full replacement: fees and payout_fees replace the existing per-currency lists, default_payout_fee becomes null if you leave it out, and default_deposit_fee becomes 0 if you leave it out. Send every value you want to keep. Leave out new_name, or repeat the current name, to keep the name. The default group can't be renamed. Returns the updated group.

Endpoint: PUT https://YOUR_NEXUS_HOST/v1/fee/group

Request body

NameTypeRequiredDescription
old_name string required Current group name.
new_name string optional New name.
default_deposit_fee number optional Default deposit fee as a fraction from 0 to 1 (0.01 = 1%).
default_payout_fee number optional Default payout fee as a fraction from 0 to 1.
fees[] array optional Per-currency deposit fees: currency_id (required), deposit_fee (fraction from 0 to 1), deposit_flat_fee (at least 0).
payout_fees[] array optional Per-currency payout fees: currency_id (required), progressive_fee (fraction from 0 to 1), flat_fee (at least 0).

Code Examples

curl -X PUT 'https://YOUR_NEXUS_HOST/v1/fee/group' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"old_name":"standard","new_name":"standard","default_deposit_fee":0.01,"fees":[{"currency_id":"ETH","deposit_fee":0.007}]}'
import requests

url = "https://YOUR_NEXUS_HOST/v1/fee/group"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
}
body = {
    "old_name": "standard",
    "new_name": "standard",
    "default_deposit_fee": 0.01,
    "fees": [{"currency_id": "ETH", "deposit_fee": 0.007}]
}

response = requests.put(url, json=body, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/fee/group", {
  method: "PUT",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "old_name": "standard",
  "new_name": "standard",
  "default_deposit_fee": 0.01,
  "fees": [{"currency_id": "ETH", "deposit_fee": 0.007}]
}),
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "id": "9c2e7a14-0b3d-4f58-8e61-2d7a9b4c1f03",
  "group_name": "standard",
  "is_default": false,
  "group_type": "Child",
  "default_deposit_fee": 0.01,
  "default_payout_fee": 0.005,
  "fees": [
    {
      "currency_id": "ETH",
      "deposit_fee": 0.008,
      "deposit_flat_fee": null,
      "updated_at": "2026-11-06T09:00:00Z",
      "is_custom": true
    }
  ],
  "payout_fees": [],
  "users": []
}
DELETE /v1/fee/group/{groupName} Delete a fee group

Delete one of your fee groups. The default group can't be deleted, and a group that still has sub-users can't be deleted either. Move them to another group first.

Endpoint: DELETE https://YOUR_NEXUS_HOST/v1/fee/group/{groupName}

Path parameters

NameTypeRequiredDescription
groupName string required Group name (URL-encoded).

Code Examples

curl -X DELETE 'https://YOUR_NEXUS_HOST/v1/fee/group/standard' \
  -H 'Authorization: Bearer YOUR_TOKEN'
import requests

url = "https://YOUR_NEXUS_HOST/v1/fee/group/standard"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
}

response = requests.delete(url, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/fee/group/standard", {
  method: "DELETE",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
  },
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "success": true,
  "message": null
}
POST /v1/fee/group/add-user Add a sub-user to a fee group

Assign a sub-user to one of your fee groups. Returns 404 (empty body) if the group or user doesn't exist, or if the user is disabled.

Endpoint: POST https://YOUR_NEXUS_HOST/v1/fee/group/add-user

Request body

NameTypeRequiredDescription
user_id string (uuid) required Sub-user id.
group_name string required Fee group name.

Code Examples

curl -X POST 'https://YOUR_NEXUS_HOST/v1/fee/group/add-user' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"user_id":"3b9d6c1e-2f4a-4c8b-9e7d-5a1f0c2b8d46","group_name":"standard"}'
import requests

url = "https://YOUR_NEXUS_HOST/v1/fee/group/add-user"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
}
body = {
    "user_id": "3b9d6c1e-2f4a-4c8b-9e7d-5a1f0c2b8d46",
    "group_name": "standard"
}

response = requests.post(url, json=body, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/fee/group/add-user", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "user_id": "3b9d6c1e-2f4a-4c8b-9e7d-5a1f0c2b8d46",
  "group_name": "standard"
}),
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "success": true,
  "message": null
}
PUT /v1/fee/group/change-user Move a sub-user to another fee group

Move one of your sub-users to a different fee group. Errors: Sub user not found, You can't manage this user.

Endpoint: PUT https://YOUR_NEXUS_HOST/v1/fee/group/change-user

Request body

NameTypeRequiredDescription
sub_merchant_id string (uuid) required Sub-user id.
new_group_name string required Target fee group name.

Code Examples

curl -X PUT 'https://YOUR_NEXUS_HOST/v1/fee/group/change-user' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"sub_merchant_id":"3b9d6c1e-2f4a-4c8b-9e7d-5a1f0c2b8d46","new_group_name":"vip"}'
import requests

url = "https://YOUR_NEXUS_HOST/v1/fee/group/change-user"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
}
body = {
    "sub_merchant_id": "3b9d6c1e-2f4a-4c8b-9e7d-5a1f0c2b8d46",
    "new_group_name": "vip"
}

response = requests.put(url, json=body, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/fee/group/change-user", {
  method: "PUT",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "sub_merchant_id": "3b9d6c1e-2f4a-4c8b-9e7d-5a1f0c2b8d46",
  "new_group_name": "vip"
}),
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "success": true,
  "message": null
}
DELETE /v1/fee/group/remove-user Remove a sub-user from a fee group

Remove a sub-user from a fee group. The ids go in a JSON request body.

Endpoint: DELETE https://YOUR_NEXUS_HOST/v1/fee/group/remove-user

Request body

NameTypeRequiredDescription
sub_user_id string (uuid) required Sub-user id.
group_name string required Fee group name.

Code Examples

curl -X DELETE 'https://YOUR_NEXUS_HOST/v1/fee/group/remove-user' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"sub_user_id":"3b9d6c1e-2f4a-4c8b-9e7d-5a1f0c2b8d46","group_name":"vip"}'
import requests

url = "https://YOUR_NEXUS_HOST/v1/fee/group/remove-user"
headers = {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
}
body = {
    "sub_user_id": "3b9d6c1e-2f4a-4c8b-9e7d-5a1f0c2b8d46",
    "group_name": "vip"
}

response = requests.delete(url, json=body, headers=headers)
print(response.status_code, response.json())
const response = await fetch("https://YOUR_NEXUS_HOST/v1/fee/group/remove-user", {
  method: "DELETE",
  headers: {
    "Authorization": `Bearer ${YOUR_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "sub_user_id": "3b9d6c1e-2f4a-4c8b-9e7d-5a1f0c2b8d46",
  "group_name": "vip"
}),
});
const data = await response.json();
console.log(response.status, data);

Example response

{
  "success": true,
  "message": null
}