Transactions

Create Lightning invoices and send payments to BOLT11 invoices or Lightning Addresses with the Amboss Payments SDK, including live progress and sandbox testing.

The transactions resource is where money moves. createReceive mints an invoice; send pays one. Both are fully typed and work against sandbox and live wallets.

Receiving

transactions.createReceive generates a Lightning invoice for a wallet. The backend mints the invoice on the node itself, so there is no team password or macaroon involved, and it behaves identically in sandbox and live.

const transaction = await payments.transactions.createReceive({
  wallet_id: walletId,
  amount: "1000", // base units (sats for BTC)
  description: "Order #1234", // optional
  expires_in_seconds: 3600, // optional
  idempotency_key: "order-1234-attempt-1", // optional
});

transaction.payment_request; // the BOLT11 invoice to share with the payer
transaction.payment_hash;

Render payment_request as a QR code or a lightning: link. Track settlement via webhooks. For the field reference and lifecycle diagram, see Receive Payments.

Sending

transactions.send mirrors the dashboard send flow. It creates the send transaction, decrypts the node admin macaroon in-process using the team password (the password never leaves your process and is never sent to the API), then executes the payment directly against the node's REST endpoint and resolves with the terminal result.

Base-asset wallets (BTC) pay over LND; Taproot Asset wallets pay over litd. The SDK picks the right endpoint automatically from the wallet's asset.

const { transaction, payment } = await payments.transactions.send({
  walletId,
  password, // team password, decrypts the node macaroon locally
  teamId, // required with a serviceApiKey (Argon2 salt); omit and it resolves from the user
  feeLimitSats: "50",
  destination: { bolt11: "lnbc1..." },
  onUpdate: ({ status }) => console.log(status), // 'IN_FLIGHT' | ...
});

payment.status; // 'SUCCEEDED' | 'FAILED'
payment.paymentHash;
payment.feeSat;
const { transaction, payment } = await payments.transactions.send({
  walletId,
  password,
  feeLimitSats: "50",
  destination: {
    lightningAddress: "[email protected]",
    amountSats: "1000",
  },
});

Send parameters

FieldTypeRequiredNotes
walletIdstringyesThe wallet the funds come from.
destinationSendDestinationyes{ bolt11, amountSats? } or { lightningAddress, amountSats }.
feeLimitSatsstringyesMaximum routing fee, in sats.
passwordstringlive onlyTeam password. Decrypts the node macaroon locally; never sent to the API.
teamIdstringwith service keyArgon2 salt. Omit and it resolves from the user.
idempotencyKeystringnoReplays return the original transaction. Strongly recommended for sends.
metadataRecord<string, string>noArbitrary annotation. In sandbox, set amb_sandbox_behavior.
timeoutSecondsnumbernoDefaults to 60.
onUpdate(progress) => voidnoFires on each lifecycle transition (INITIATED, IN_FLIGHT, SUCCEEDED, FAILED).
signalAbortSignalnoAbort an in-flight payment.

A wrong password throws DecryptionError; a node-side failure throws PaymentSendError. See Errors.

Sandbox sends

Sandbox wallets need no node, no macaroon, and no password. Just call send and the backend settles the transaction for you. payment comes back null; observe the outcome via webhooks or by polling the transaction status. The backend settles asynchronously per the amb_sandbox_behavior metadata (complete, fail, or expire; default expire).

const { transaction, payment } = await payments.transactions.send({
  walletId, // a sandbox wallet, no password required
  feeLimitSats: "50",
  destination: { bolt11: "lnbc1..." },
  metadata: { amb_sandbox_behavior: "complete" }, // force success in sandbox
});

payment; // null, settlement happens server-side

For network constraints, idempotency semantics, and how to inspect a failed send, see Send Payments.

Next steps