Skip to main content

Addresses

An address is the on-chain endpoint your vault uses to receive deposits and send funds. Every address is deterministically derived from the vault's master key using BIP-44 (soft derivation) and is bound to a single account inside the vault.

Each address is represented by a stable platform-side ID (id) plus the chain-native address string (networkAddress); the API always works with idnetworkAddress is for human display and on-chain interactions.

How addresses are derived

The platform builds an address from a 5-component HD path:

m/44/<coinType>/<accountIndex>/<change>/<addressIndex>
ComponentDefaultWhat it controls
coinTypethe network's SLIP-44 (e.g. 60 for Ethereum, 0 for Bitcoin)The chain "namespace" inside BIP-44.
accountIndexfrom the account's index (set when the account is created)Logical account within the vault — same for every address of that account.
change00 = external/receiving address, 1 = internal/change address.
addressIndexnext free index for this (account, coinType, change)Per-account counter; the platform allocates the next value automatically.
typenetwork-specific (e.g. p2wpkh for Bitcoin)Address format. See Address types.

When you call POST /addresses without any of coinType, change, addressIndex, the platform picks the defaults above and allocates the next free addressIndex. To target a specific HD path slot, see Custom HD path.

The full HD path is returned on every address as hdpath — useful for audit and reproducibility.

Create an address

curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"accountId": "eFjwUQXB8CMnrTHSgYzaL6",
"network": "ethereum-mainnet",
"name": "Customer Deposits"
}' \
https://api.carabaas.com/api/v1/addresses

Request body:

FieldRequiredNotes
accountIdyesExisting account inside an active vault.
networkyesReal network (e.g. ethereum-mainnet, bitcoin-mainnet) or the virtual @eth-like (see below).
nameyesHuman-readable label, unique within the account (3–128 chars). Doubles as an idempotency key — see below.
typenoAddress format for chains with multiple formats (e.g. p2wpkh, p2pkh for Bitcoin).
coinTypenoOverride the SLIP-44 used in the HD path. If set, change and addressIndex become required.
changeno0 (external) or 1 (internal). Required when coinType or addressIndex is provided.
addressIndexnoPin a specific slot. If set, change becomes required.
datanoFree-form JSON object you can attach to the address (e.g. your internal customer ID).

Caller must hold generateDetails permission on the address's vault.

Response codes

  • 201 Created — a new HD slot was allocated and an on-chain address was generated.
  • 200 OK — an address with this name already exists in the account and all provided parameters match — the existing record is returned as-is. Use this to make creation idempotent: re-issuing the same request after a network blip is safe.
  • 409 Conflict — a name conflict where parameters differ (e.g. same name but a different network or addressIndex), or an HD-path conflict that violates address exclusivity.

Idempotency by name

name is unique per account and acts as the client-side idempotency key. The platform uses it to recognize a retried request and return the existing address instead of generating a new one — provided every supplied attribute matches the stored record (network, type, coinType, change, addressIndex, data).

Two practical consequences:

  • Always pick a name that uniquely identifies the address from your side (a customer ID, a deposit-flow tag, etc.).
  • If you change any parameter under the same name, you'll get 409 ADDRESS_AMBIGUOUS — pick a different name instead.

Address types

Address type controls the on-chain address format. It only matters for chains that support multiple formats.

NetworkAllowed typeDefault if omittedNotes
Bitcoin & UTXO forksp2wpkh, p2pkhnone — type is requiredSee Bitcoin & UTXO Chains.
Account-based chains (Ethereum, Solana, Tron, etc.)(omit)internal defaultThe chain has only one address format; you don't need to set type.

Two addresses can coexist at the same HD-path slot if their type differs (e.g. a p2pkh and a p2wpkh Bitcoin address derived from the same path are independent on-chain addresses).

ETH-like universal addresses

Most EVM chains share an identical address derivation. Instead of generating a separate address per chain, you can target the virtual network @eth-like:

curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"accountId": "eFjwUQXB8CMnrTHSgYzaL6",
"network": "@eth-like",
"name": "Universal EVM Address"
}' \
https://api.carabaas.com/api/v1/addresses

A single @eth-like address is reachable on Ethereum, Polygon, BSC, Arbitrum, Optimism, Avalanche, and every other EVM-compatible chain the platform supports — present and future. Balances returned for it (see Get an address with balances) aggregate across all those chains.

Upgrading an existing chain-specific address

If you already created an address for a single EVM chain (say ethereum-mainnet) and later want it to receive on every EVM chain, repeat the create call with the same name but network: "@eth-like":

curl -X POST -d '{
"accountId": "...",
"network": "@eth-like",
"name": "Customer Deposits" # same name as the existing ethereum-mainnet address
}' ...

The platform recognizes the request as an in-place upgrade: the address keeps its id and networkAddress, but its network field flips to @eth-like and the address starts being recognized on every EVM chain. The reverse — downgrading @eth-like to a single chain — is not supported.

Address exclusivity

A single HD-path slot (the (account, coinType, change, addressIndex, type) tuple) can hold either one virtual address or one or more non-virtual addresses on different chains — never both at the same time.

In practice this means:

  • If you have an @eth-like address at a given slot, you cannot create a chain-specific (e.g. polygon-mainnet) address at the same slot. Use the virtual address — it already covers Polygon.
  • If you have one or more chain-specific addresses at a slot (e.g. ethereum-mainnet and bitcoin-mainnet — yes, they live at different coinType values, so this example would be at different slots; but two ETH-only addresses on different EVM networks would share a slot), you cannot create an @eth-like address at that slot until you upgrade one of them as described above.

A violation surfaces as 409 with code ADDRESS_AMBIGUOUS.

Custom HD path

You can pin one or more HD-path components instead of letting the platform pick them:

{
"accountId": "eFjwUQXB8CMnrTHSgYzaL6",
"network": "ethereum-mainnet",
"name": "Reserve Wallet #5",
"coinType": 60,
"change": 0,
"addressIndex": 5
}

Constraints:

  • coinType: integer, 0 ≤ coinType ≤ 2_147_483_647. If provided, both change and addressIndex must also be provided.
  • change: integer, 0 or 1.
  • addressIndex: integer, 0 ≤ addressIndex ≤ 2_147_483_647. If provided, change must also be provided.

Pinning addressIndex to a value below the current platform-allocated counter is allowed — the next auto-allocation simply jumps to max(currentPointer, pinnedIndex) + 1 so you don't get collisions.

Get an address with balances

curl -H "Authorization: Bearer $TOKEN" \
https://api.carabaas.com/api/v1/addresses/{addressId}

The response is the address record plus a balances array — one entry per (network, asset) the address holds. For an @eth-like address you'll see one entry per EVM chain on which the address has any balance.

Update an address

You can rename or update the attached data; the on-chain address itself is immutable.

curl -X PATCH \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Customer Deposits — archived",
"data": { "archivedAt": "2026-04-29" }
}' \
https://api.carabaas.com/api/v1/addresses/{addressId}

Both fields are optional. name must remain unique within the account (409 Conflict otherwise). Caller needs edit on the vault.

List addresses

curl -H "Authorization: Bearer $TOKEN" \
"https://api.carabaas.com/api/v1/addresses?organizationId=djk2wDuMhsx9KR2r7JgBQW"

organizationId is required. Results are scoped automatically to vaults the caller can read; without Vault:read (global) or manageVaults on the org, the list is restricted to vaults explicitly granted to the caller.

Query parameters

ParameterTypeNotes
organizationIdstringRequired.
filter[vaultId]string[]Filter by vault IDs.
filter[accountId]string[]Filter by account IDs.
filter[network]string[]Filter by networks. A real EVM network (e.g. polygon-mainnet) automatically also matches @eth-like addresses, since those addresses are reachable on that network.
filter[addressIndex]number[]Filter by HD-path addressIndex.
filter[format]string[]Filter by address type (p2wpkh, p2pkh, default).
relations[]enum[]Include related entities. Supported: account, balances. balances requires a single value in filter[vaultId] (otherwise the request is rejected).
searchstring (≥ 3)Substring match on name, networkAddress, or hdpath.
pagenumberDefault 0.
pageSizenumberDefault 100, max 1000.
# Filter by vault
curl "...?organizationId=djk2wDuMhsx9KR2r7JgBQW&filter[vaultId][]=kR7mNpX2wQvL9sYhBjD4eT"

# Search by name, address, or HD path
curl "...?organizationId=djk2wDuMhsx9KR2r7JgBQW&search=customer"

# Include balances (single vault required)
curl "...?organizationId=djk2wDuMhsx9KR2r7JgBQW&filter[vaultId][]=kR7mNpX2wQvL9sYhBjD4eT&relations[]=balances"

Validate / canonicalize an address

Before using a third-party destination, run it through the canonicalizer to (a) check it parses for the target network and (b) get the platform's preferred form back:

curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"network": "ethereum-mainnet",
"address": "0x742d35Cc6634C0532925a3b8..."
}' \
https://api.carabaas.com/api/v1/addresses/canonicalize
{
"data": {
"canonical": "0x742d35cc6634c0532925a3b8...",
"formats": [ { "format": "checksum", "address": "0x742d35Cc..." } ],
"features": { "requireMemo": false },
"metadata": { /* network-specific metadata, e.g. account flags */ }
}
}

What you get:

  • canonical — the form the platform stores and matches against (e.g. lowercase for EVM, base58check for Bitcoin).
  • formats — alternative valid renderings of the same address.
  • features.requireMemo — for chains where the destination demands a memo/destination tag (currently surfaced for Ripple, derived from the on-chain requireDestinationTag flag). Treat true as a hard signal to require a memo on every transaction to that address.
  • metadata — chain-specific extras (account flags, sequence numbers, …).

The endpoint is rejected (404) for virtual networks like @eth-like. An invalid address returns 400 Invalid address provided.

tip

Always canonicalize external destinations before creating a transaction or saving them to an address book.

ERC-20 / TRC-20 allowance

Inspect how much a third-party spender is allowed to pull from one of your addresses for a given token contract:

curl -H "Authorization: Bearer $TOKEN" \
"https://api.carabaas.com/api/v1/addresses/{addressId}/allowance?network=ethereum-mainnet&spender=0xSpender...&asset=c60_t0x779877A7B0D9E8603169DdbD7836e478b4624789"

Query parameters (all required):

ParameterDescription
networkAn ETH-like network or tron-*. Virtual networks are not supported.
spenderThe third-party address allowed to spend.
assetA platform asset ID for an ERC-20 or TRC-20 token.

For setting / changing allowances, see Ethereum & EVM Chains — ERC-20 allowances.

Stellar trustlines

For Stellar addresses you can list the trustlines currently configured on-chain:

curl -H "Authorization: Bearer $TOKEN" \
https://api.carabaas.com/api/v1/addresses/{addressId}/trustlines

Returns an array of platform asset IDs (one per trustline). Only stellar-* addresses are accepted; everything else returns 400.

To open a new trustline, see Stellar & Ripple — Trustlines.

Tezos: check whether an address is revealed

Tezos requires every address to be revealed (its public key published on-chain) before it can sign outgoing operations. Check the current state:

curl -H "Authorization: Bearer $TOKEN" \
https://api.carabaas.com/api/v1/addresses/{addressId}/is-revealed
{ "network": "tezos-mainnet", "addressId": "...", "networkAddress": "tz1...", "revealed": false }

Only Tezos addresses are accepted. To perform the reveal operation, see Tezos Reveal.

See also