Quickstart
This page takes a hosted Testnet API key to a completed mint of 100.00 USDX. Every request below runs in CI against an in-process core on FakeChain, so a response that stops matching its # expect line fails the build.
You need an API key for an org with approved KYB and the counterparties:write and transfers:write scopes; the hosted issuer's dev-org command prints one. Three placeholders stand in for your values: {{KEY}} is your API key, {{uuid}} is a fresh idempotency key the runner fills in, and {{WALLET_ADDRESS}} is your funded Testnet wallet. On a hosted issuer you fund that wallet through Friendbot first:
curl -s "$API/v1/sandbox/testnet/fund" -H "authorization: Bearer $KEY" -H "idempotency-key: $(uuidgen)" \
-H 'content-type: application/json' -d '{"address":"<WALLET_ADDRESS>"}'
The docs runner funds {{WALLET_ADDRESS}} before the first request, so the block above stays plain bash.
Register and prove the wallet
Create a stellar_wallet counterparty. The response carries an ownership challenge, and only the wallet's key can sign it. Lines starting with # are directives the docs runner reads, not part of the request: # expect is the status the request must return, # save carries a response value into a later request, and # sign stands in for signing a saved XDR with the page's test wallet. On a hosted issuer you sign locally instead, the way the README's sign.mjs does.
POST /v1/counterparties
authorization: Bearer {{KEY}}
idempotency-key: {{uuid}}
content-type: application/json
{
"type": "stellar_wallet",
"address": "{{WALLET_ADDRESS}}",
"label": "quickstart"
}
# expect 201
# save CPTY = $.id
# save CHALLENGE = $.ownership_proof.challenge_xdr
# sign SIGNED_CHALLENGE = CHALLENGE
Submit the signed challenge. The wallet becomes active.
POST /v1/counterparties/{{CPTY}}/ownership-proof
authorization: Bearer {{KEY}}
idempotency-key: {{uuid}}
content-type: application/json
{
"signed_challenge_xdr": "{{SIGNED_CHALLENGE}}"
}
# expect 200
Add the trustline
An active wallet still needs a trustline to the asset, and the issuer sponsors it. 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, so keep the signing step close by.
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
Mint and settle the wire
Create a mint transfer from an inbound wire to the wallet. The response's deposit_instructions.reference is the wire reference. If the trustline has not landed yet this answers destination_no_trustline, so retry with a fresh idempotency key.
POST /v1/transfers
authorization: Bearer {{KEY}}
idempotency-key: {{uuid}}
content-type: application/json
{
"source": { "type": "fiat", "currency": "USD", "rail": "wire" },
"destination": { "type": "stellar", "asset": "USDX", "counterparty_id": "{{CPTY}}" },
"amount": "100.00"
}
# expect 201
# save TRANSFER = $.id
# save REFERENCE = $.deposit_instructions.reference
Simulate the incoming wire with the sandbox endpoint, quoting the reference. A matching wire credits the org and the mint proceeds.
POST /v1/sandbox/fiat-deposits
authorization: Bearer {{KEY}}
idempotency-key: {{uuid}}
content-type: application/json
{
"reference": "{{REFERENCE}}",
"amount": "100.00",
"currency": "USD"
}
# expect 201
Read the transfer back. It is completed once the mint has been submitted and confirmed on chain.
GET /v1/transfers/{{TRANSFER}}
authorization: Bearer {{KEY}}
# expect 200
The completed transfer carries a stellar_tx_hash; open it in an explorer to see the mint arrive in the wallet.