Integrate server-side. Run registration, quoting and ordering from your backend with your API key. The signature that approves an order comes from whoever holds the signer key. For a copy-paste sandbox script, see the sandbox onramp.
Embedded wallets run on Stellar, so the wallet’s chain is
stellar. All endpoints use the raw API key in the Authorization header (no Bearer prefix); see Authentication. You do not need Stellar’s rules (trustlines, reserves, transaction expiry) to use an embedded wallet; we handle them for you.Who holds the key
You, the integrating partner, choose who holds the signer key:- You hold the signer key yourself, on behalf of your program; or
- Your end customer holds and controls the signer key, so only the customer can approve an order and you never hold or see the customer’s private key.
Whether holding the key makes you a custodian or money transmitter depends on your own facts, activities, and jurisdiction. This is not legal advice; determine your own obligations with your legal and compliance advisors.
Register the wallet
We create the embedded wallet when you register it. First, the key holder generates a P-256 key pair and keeps the private key. Then you register the public key withPOST /organization/{organizationId}/payment_account. Use the id of the organization that owns the wallet: your own organization’s id from GET /me, or the customer organization’s id. The examples below set it as $ORGANIZATION_ID, and the quote and order use the same id. See Organizations in the route.
Send kind embeddedWallet, and accountDetails of kind signerPublicKey with the chain and the signerPublicKey. signerPublicKey is the hex-encoded P-256 public key in SEC1 form, compressed (33 bytes) or uncompressed (65 bytes). The chain is stellar today.
id: you pass it to every quote that moves money into or out of the wallet.
GET /organization/{organizationId}/payment_accounts.
Quoting and ordering
You quote and order an embedded wallet like any other wallet. Pass the wallet’s payment accountid as destination on an onramp quote, or as source on an offramp quote. The other side is the bank account’s payment account. Both accounts must belong to the organization in the route.
destinationAsset from a token’s asset in GET /supported_assets?chain=stellar. The quote prices the account reserve and trustline a new wallet needs into its fee lines, so a new wallet gets its first funds from its first onramp and you never send XLM.
Create the order with POST /organization/{organizationId}/order and the quoteId. The order’s id is the quoteId. For the rest of each direction, see Onramps and Offramps.
Order authorization
When an order needs the key holder to approve moving the wallet’s funds, the order’sauthorization field holds the request. Otherwise authorization is null. Read it from GET /organization/{organizationId}/order/{id} or from the orderUpdated webhook.
reason tells you why we need the approval:
The order status does not change while the authorization waits. The order stays
created (for funding) or claimable (for claim). We send orderUpdated when authorization appears or changes. An order has at most one pending authorization at a time.
An offramp or swap funded from an embedded wallet has no address to send to. Its fundingInstructions.destination carries the authorization id:
Sign the message
The key holder signsmethod.message with the signer key:
es256: ECDSA over P-256 with SHA-256.- Sign the UTF-8 bytes of
method.messageexactly as we return it. - Hex-encode the signature. We accept DER, or the 64-byte
r||sform (128 hex characters) that WebCrypto produces.
Submit the approval
Send the authorizationid and the signature to POST /organization/{organizationId}/order/{id}/authorization:
Errors and expiry
Each authorization expires at
expiresAt. When one expires, we replace it with a new authorization that has a new id and a new message, and we send orderUpdated. Always sign the authorization you just read, and never reuse an old signature. See Errors for the error body format.
Claiming funds
The first time an embedded wallet receives an asset, it has no trustline for it. The asset arrives as a Stellar claimable balance, and the order moves toclaimable. This comes from how Stellar works, not from Etherfuse. The order’s claimInstructions describes the balance:
POST /organization/{organizationId}/order/{id}/claim with no body. For an embedded wallet we return the id of the order’s claim authorization:
completed. A self-held wallet gets kind stellarTransaction with an xdr to sign and submit instead.
Tracking the order
Subscribe toorderUpdated with POST /webhook_subscription. Each delivery carries the full order, so you see a new or replaced authorization, the move to claimable, and then the move to completed without polling. GET /organization/{organizationId}/order/{id} is the fallback. See Webhooks.
Related
Sandbox onramp
Minimal server-side onramp script for sandbox