Counterparties and trustlines
A counterparty is a party money can move to or from. There are two kinds: a bank_account, which receives fiat, and a stellar_wallet, which receives tokens. Both belong to the organisation and are created with POST /v1/counterparties.
A wallet also needs a trustline to the asset before tokens can reach it. Single-wallet responses carry a checks object that reports whether the account and its trustline exist, and whether the issuer can sponsor a missing one. When the trustline is missing, the issuer sponsors it: the platform prepares a sponsor-signed offer, the wallet co-signs, and the platform submits the result.
Every request on this page runs in CI against an in-process core on FakeChain, so a response that stops matching its # expect line fails the build.
Create a bank counterparty
A bank account is ready to use as soon as it is created.
POST /v1/counterparties
authorization: Bearer {{KEY}}
idempotency-key: {{uuid}}
content-type: application/json
{
"type": "bank_account",
"label": "Ops account",
"beneficiary_name": "Acme Testnet Ltd",
"bank_name": "Testnet mock bank",
"account_number": "GB00TEST12345678",
"routing_code": "TEST0001",
"currency": "USD"
}
# expect 201
# save BANK = $.id
Create a wallet counterparty
A wallet counterparty is created pending_verification. The response carries an ownership challenge, and only the wallet's key can sign it.
POST /v1/counterparties
authorization: Bearer {{KEY}}
idempotency-key: {{uuid}}
content-type: application/json
{
"type": "stellar_wallet",
"address": "{{WALLET_ADDRESS}}",
"label": "counterparties guide"
}
# expect 201
# save CPTY = $.id
# save CHALLENGE = $.ownership_proof.challenge_xdr
# sign SIGNED_CHALLENGE = CHALLENGE
Read the trustline checks
Read the wallet with GET /v1/counterparties/{id}. The checks object reports the account and trustline state. Here the account is present and the trustline is missing. The wallet is still pending_verification, so no sponsored-trustline offer is available yet; it becomes available once the wallet is active.
GET /v1/counterparties/{{CPTY}}
authorization: Bearer {{KEY}}
# expect 200
Prove control
Submit the signed challenge with POST /v1/counterparties/{id}/ownership-proof. The wallet becomes active. Sponsorship is offered only for active wallets, because it spends the issuer's reserve.
POST /v1/counterparties/{{CPTY}}/ownership-proof
authorization: Bearer {{KEY}}
idempotency-key: {{uuid}}
content-type: application/json
{
"signed_challenge_xdr": "{{SIGNED_CHALLENGE}}"
}
# expect 200
Sponsor the trustline
Ask for the offer, co-sign the returned envelope with the wallet key, then submit the hash and the signed envelope together. The offer expires about a minute after it is issued.
POST /v1/counterparties/{{CPTY}}/sponsored-trustline
authorization: Bearer {{KEY}}
idempotency-key: {{uuid}}
content-type: application/json
{}
# expect 200
# save TRUSTLINE_HASH = $.hash
# save TRUSTLINE_ENVELOPE = $.envelope_xdr
# sign SIGNED_TRUSTLINE = TRUSTLINE_ENVELOPE
POST /v1/counterparties/{{CPTY}}/sponsored-trustline/submit
authorization: Bearer {{KEY}}
idempotency-key: {{uuid}}
content-type: application/json
{
"hash": "{{TRUSTLINE_HASH}}",
"signed_envelope_xdr": "{{SIGNED_TRUSTLINE}}"
}
# expect 200
Read the checks again
Read the wallet once more. The trustline is now present, and no further offer is made.
GET /v1/counterparties/{{CPTY}}
authorization: Bearer {{KEY}}
# expect 200