nodana

Introduction

Use the Nodana API to create and manage hosted nodes and webhook receivers. Use your node’s Phoenixd API for invoices, Lightning payments, balances, channels and LNURL services.

API addresses

APIBase URLAuthentication
Nodana managementhttps://api.nodana.io/v1Bearer API key
PhoenixdYour node’s HTTPS URLHTTP Basic with an empty username and Phoenixd password

Host attestation uses your node’s HTTPS URL without an Authorization header.

Examples use https://node-a1b2.nodana.app as a dummy node URL. Replace it with your node’s complete HTTPS connection URL. Keep API keys and passwords in your backend’s secret configuration.

Nodana management endpoint paths are relative to https://api.nodana.io/v1; requests use JSON bodies. Phoenixd endpoint paths are relative to your node URL; POST parameters use form data and payment-history filters use query parameters. See Authentication.

Manage hosted nodes

  • Create a node: start provisioning and save the one-time credentials returned in the response.
  • List nodes: find your node IDs and statuses.
  • Update a node: select and apply an available release.
  • Webhooks: receive and verify payment notifications.
  • Attestation: request evidence for client-side verification of a protected Nodana host.

Work with Phoenixd

  • Payments: create invoices and offers, send funds, track payments and export history.
  • Node: inspect balances and channels, decode payment requests and estimate liquidity fees.
  • LNURL: pay, withdraw and authenticate with LNURL services.
  • WebSocket: subscribe to incoming payments.

The upstream reference describes the daemon API.

See Responses, Error handling and Rate limiting. Compact endpoint lists are available for the Nodana API and Phoenixd API.

Authentication

Choose credentials for the API you are calling: a Nodana account API key for hosted-node and webhook management, or your node’s Phoenixd password for payments and node information.

Nodana

For direct API integrations, authenticate node operations with an API key in the Authorization header.

Create an API key

In the dashboard, open Developers, then API Keys. Create a key for your integration and select the permissions it needs. Save the full key when it is shown; it cannot be retrieved later.

Send authenticated requests

Send your key as Authorization: Bearer YOUR_API_KEY. Replace the placeholder with your API key.

For Lightning operations, use your node URL and Phoenixd password with the Phoenixd API or CLI.

Permissions

PermissionScopeOperations
Nodes → Readnodes:readList nodes, read details, check available updates and read webhook settings and deliveries
Nodes → Writenodes:writeCreate, rename, start, stop, restart, update or delete nodes; create, change or delete their webhook endpoint

Write also requires Read. Choose the minimum permissions your integration needs.

Keys belong to one account. The API uses the key to determine your account; you do not need to send an account ID. The key must include the required permission. Missing, invalid, disabled, or revoked keys and insufficient permissions return 401 Unauthorized. Nodes belonging to another account return 404 Not Found.

Keep keys private

Use keys from your backend or trusted scripts. Store them in secret storage, keep them out of browser code and source control, and revoke or replace them if exposed.

A Nodana API key authenticates calls to the Nodana API. Your node's Phoenixd password is a separate credential for direct calls to its Phoenixd API.

Phoenixd

Use HTTP Basic authentication with an empty username and your Phoenixd password. Replace the dummy URL with your node’s connection URL and keep PHOENIXD_PASSWORD in your backend’s environment or secret storage. JavaScript examples in this reference run on the server with Node.js.

Phoenixd creates its passwords on first start. For a self-hosted daemon, find http-password and http-password-limited-access in ~/.phoenix/phoenix.conf, or the corresponding directory on your persistent volume.

The full password permits all operations, including spending funds. Prefer the limited password for reading information and creating invoices. Each endpoint page states the access it needs. Use the full password for spending, channel closure and other operations marked as full access.

For remote requests, use the complete HTTPS connection URL and leave certificate verification enabled. Keep both passwords private, including the limited password. Store them in backend secret settings and replace exposed credentials on the node. Do not put credentials in browser code, URLs or source control.

Attestation

The node’s attestation endpoint does not require a Phoenixd password or Nodana API key. Supply the challenge described on its endpoint page without an Authorization header.

Responses

Read the response format on each endpoint page. Nodana management and Phoenixd return different response shapes and timestamp units.

Nodana

Node reads and start, stop, restart and update operations return node metadata. Lists wrap objects in nodes. Creation returns {node, credentials}; save the one-time recovery seed and passwords from credentials when the response arrives. Node creation and lifecycle operations continue in the background after 202 Accepted. Node deletion returns 202 with no body.

Node response fields

FieldTypeDescription
idstringNodana node ID
namestringDisplay name
regionstringHosting region
imagestringNode software image identifier
accessModestringNode access mode
statusstringNode lifecycle state
publicUrlstring or nullPhoenixd HTTPS URL, or null while being set up
failureMessagestring or nullPublic failure message
updateStatusstring or nullUpdate progress or outcome
updateCompletedAtinteger or nullUpdate completion time in Unix seconds
lastCheckedAtinteger or nullLast status check in Unix seconds
createdAtintegerCreation time in Unix seconds
updatedAtintegerLast change time in Unix seconds

Node states

Node states include provisioning, ready, starting, stopping, stopped, restarting, updating, failed, deleting, deleted and cordoned. stopped means the user took the node offline; cordoned means it was suspended because the account ran out of credit.

For shared response handling, see Error handling and Rate limiting.

Webhook responses

Reading a receiver returns {endpoint: {...}}, or {endpoint: null} when none is configured. Creating one returns {endpoint, signingSecret}; save the secret immediately because it is only returned once. Updating returns the endpoint object, and deleting returns 204 No Content without a body.

Delivery history wraps the latest 50 records in deliveries. Its timestamps, and node metadata timestamps, use Unix seconds.

Phoenixd

Read the response format on each endpoint page. Phoenixd returns JSON objects or arrays for structured results, and plain text for offers, addresses and some node actions. Invoice creation returns the invoice in serialized alongside its paymentHash.

Payment lists are arrays, paginated with limit and offset. Date filters and payment timestamps use Unix milliseconds. Fields named amountSat, balanceSat, receivedSat and feeCreditSat use satoshis. Payment-history fees values use millisatoshis; do not infer their unit from the routingFeeSat field returned by a payment attempt.

Optional fields can be absent. Read isPaid to confirm a payment and check receivedSat against the expected order amount. Preserve the payment hash or ID so you can look up an uncertain result. See Error handling.

Error handling

Check the HTTP status and response body before treating an operation as successful. Handle errors according to the API you called.

Nodana

Check the HTTP status before reading a response as a successful result. API errors return an error object containing a stable code and a human-readable message.

Use the code and status for application logic. Keep the message for diagnostics rather than matching its wording.

Status codes

For 400, check the input and the operation's state requirements. For 401, check your key and permissions. For 404, check the node ID and whether it was deleted. For 429, wait for the Retry-After interval.

If credit or billing prevents the operation (402), resolve the account's credit or billing state. Server and upstream failures (500, 502, 503) require checking the outcome before retrying a mutation.

Malformed JSON or unsupported request content types may be rejected before the endpoint runs. Handle unexpected or non-JSON error bodies as well.

Retry carefully

Retry reads after transient failures using bounded exponential backoff. For 429 responses, follow the rate limiting guidance.

A timeout or connection error does not establish that a mutation failed. Check node state before repeating a lifecycle operation. After an interrupted create request, list your nodes and reconcile the outcome before trying again. Each creation attempt requires a new requestId; repeating an accepted request returns 409 Conflict. Credentials are returned only once. If the node was created but you did not receive its credentials, contact Nodana before attempting another creation.

A 202 Accepted creation response means provisioning is still in progress. A successful update request also starts background work; inspect the node to determine the final outcome.

Phoenixd

Check the HTTP status and the endpoint's response body before treating an operation as successful. Response bodies vary by operation.

For 401, check the Phoenixd password, empty Basic-auth username and the endpoint's required access. For invalid parameters, check the field names, amount units and form encoding. If a payment lookup returns 404, check the hash or payment ID and the node URL.

A successful HTTP response alone does not establish that money moved. Inspect the returned payment or action result and use Get incoming payment or Get outgoing payment to confirm its outcome.

Interrupted requests

If an outgoing payment times out, look it up before submitting another payment. A lost response does not mean the payment failed. Save payment IDs and hashes in your backend so you can reconcile them.

Keep your application's invoice creation and fulfilment records. Use externalId to associate invoices with orders and list incoming payments to find them after an interrupted request. Reusing an external ID does not prevent another invoice from being created.

Rate limiting

Limit concurrency and avoid tight polling loops. The Nodana management API and your node’s Phoenixd connection have separate throttling behaviour.

Nodana

Node operations share a request limit per client IP address. Requests from applications behind the same outbound IP count towards the same limit, even when they use different API keys.

Most Nodana operations default to 180 requests per 60-second window. Node creation uses a separate default limit of 10 requests per 60 seconds. Use the response headers to decide when to retry; deployed limits can change.

Rate-limit responses

When the limit is exceeded, the API returns 429 Too Many Requests with these headers:

Retry-After tells you how many seconds to wait before retrying. X-RateLimit-Limit and X-RateLimit-Remaining describe the window, while X-RateLimit-Reset is a reset interval in seconds rather than a Unix timestamp.

These headers are returned on rate-limit errors. Do not rely on receiving them with every successful request.

View response headers

Use curl -i to include response headers when inspecting a request.

Handle throttling

Wait at least the Retry-After interval before retrying, and add a small random delay when multiple workers share an IP. Limit concurrent requests and avoid tight polling loops during node provisioning or updates.

For network failures and other transient errors, use bounded backoff rather than continuously retrying. See Error handling for reconciling requests whose outcome is uncertain.

Phoenixd

Control concurrency in your client and avoid tight polling loops. Use WebSocket for incoming payment notifications, and query payment history to reconcile missed events.

Handle throttling

If your connection endpoint returns 429 Too Many Requests, pause requests and follow Retry-After when present. It tells you how many seconds to wait. Reduce concurrency if requests continue to be throttled.

For network failures and other transient errors, use bounded backoff. Check the outcome of an interrupted payment before sending it again. See Error handling.

Inspect response headers

Use curl -i to include response headers when inspecting a request.

List nodes

List the active nodes in your account. Deleted nodes are excluded.

GET/nodes

Required permission: Nodes → Read.

Create a node

Start setting up a Phoenixd node in your account.

POST/nodes

Required permission: Nodes → Write.

Body parameters

requestIdstringRequired

A random 128-bit identifier encoded as 32 hexadecimal characters. Use a new identifier for each creation attempt. Repeating an accepted request returns a conflict.

namestringOptional

Display name, up to 16 characters after trimming. Omit it or leave it blank to use a generated name.

autoLiquiditystringRequired

Choose 2m, 5m or 10m for automatic liquidity.

The response contains node metadata and one-time credentials: the recovery seed, full-access password and restrictedPassword. Save the credentials in your secret store when this response arrives. Keep them out of logs and conversation output. The node continues launching in the background; use Get a node to check its status before sending payments. If launch fails, discard these credentials and create a new node.

Creation requires sufficient account credit and available capacity. A 402 response means you need to add credit; a 503 node_capacity_unavailable response means capacity is currently full.

Get a node

Return a node's details without its passwords or recovery seed.

GET/nodes/{nodeId}

Required permission: Nodes → Read.

Path parameters

nodeIdstringRequired

ID of the node in your account. Use List nodes to find its ID.

Rename a node

Change the display name of a node.

PATCH/nodes/{nodeId}

Required permission: Nodes → Write.

Path parameters

nodeIdstringRequired

ID of the node in your account. Use List nodes to find its ID.

Body parameters

namestringRequired

New display name for the node. Must be non-blank and contain no more than 16 characters after trimming.

Start a node

Start a stopped or failed node. The node starts in the background.

POST/nodes/{nodeId}/start

Required permission: Nodes → Write.

Path parameters

nodeIdstringRequired

ID of the node in your account. Use List nodes to find its ID.

The node must have status stopped or failed. Other states return 400 Bad Request.

Stop a node

Stop a node while retaining its data.

POST/nodes/{nodeId}/stop

Required permission: Nodes → Write.

Path parameters

nodeIdstringRequired

ID of the node in your account. Use List nodes to find its ID.

The node must have status ready. Its payment API is unavailable while stopped, and incoming requests cannot restart it. Stopping a node does not pause billing.

Restart a node

Stop and start an existing node.

POST/nodes/{nodeId}/restart

Required permission: Nodes → Write.

Path parameters

nodeIdstringRequired

ID of the node in your account. Use List nodes to find its ID.

The node must have status ready. Its payment API is temporarily unavailable during the restart.

Check for an update

Return the current node release and any supported update, using the same availability check as the dashboard.

GET/nodes/{nodeId}/update

Required permission: Nodes → Read.

Path parameters

nodeIdstringRequired

ID of the node in your account. Use List nodes to find its ID.

Review the target release before submitting its releaseSha256 to Update a node.

availableUpdate is null when there is no supported update. Its version identifies the node release. currentRelease contains the running release identity. currentVersion is the bundle version; currentRelease.phoenixdVersion identifies Phoenixd. The current version may be null while the node is unavailable.

Update a node

Begin the supported node update you have approved. The update continues in the background.

POST/nodes/{nodeId}/update

Required permission: Nodes → Write.

Path parameters

nodeIdstringRequired

ID of the node in your account. Use List nodes to find its ID.

Use Check for an update first. If availableUpdate is null, there is no update to apply. Otherwise, review that release and send its releaseSha256 in the JSON body. This uses the same update flow as the dashboard. The server checks availability again before accepting the request.

The node must have status ready and an available update. The initial response has status updating; it does not indicate that the update has completed. Node data is retained.

Delete a node

Permanently remove a node.

DELETE/nodes/{nodeId}

Required permission: Nodes → Write.

Path parameters

nodeIdstringRequired

ID of the node in your account. Use List nodes to find its ID.

Reconcile outstanding payments, handle remaining funds, and retain recovery information before deleting. Bearer API-key requests do not require a two-factor code.

Get webhook endpoint

Read the webhook receiver configured for your node.

GET/nodes/{nodeId}/webhook-endpoint

Required permission: nodes:read. See Authentication.

Path parameters

nodeIdstringRequired

ID of the node in your account. Find it with List nodes.

Returns { "endpoint": null } if no endpoint is configured. The signing secret is returned only when creating an endpoint.

Create webhook endpoint

Configure your node to deliver payment notifications to your application.

POST/nodes/{nodeId}/webhook-endpoint

Required permission: nodes:write. See Authentication.

Path parameters

nodeIdstringRequired

ID of the node in your account. Find it with List nodes.

Body parameters

urlstringRequired

A public HTTPS receiver URL, up to 2048 characters, without embedded credentials.

descriptionstringOptional

Optional description, up to 500 characters after trimming.

Each node supports one endpoint. An existing endpoint returns 409 webhook_endpoint_already_exists. Save the returned signingSecret in your receiver’s secret settings before processing events. See Webhook authentication.

Update webhook endpoint

Change the receiver URL, description or whether delivery is enabled.

PATCH/nodes/{nodeId}/webhook-endpoint

Required permission: nodes:write. See Authentication.

Path parameters

nodeIdstringRequired

ID of the node in your account. Find it with List nodes.

Body parameters

urlstringOptional

A public HTTPS receiver URL, up to 2048 characters, without embedded credentials.

descriptionstringOptional

Optional description, up to 500 characters after trimming.

enabledbooleanOptional

Whether to deliver payment notifications.

Supply at least one field. Omitted fields keep their current values. Use an empty description to clear it. Disabling cancels queued deliveries and stops new notifications. Re-enabling starts delivery for future events.

Delete webhook endpoint

Remove the webhook receiver configured for your node.

DELETE/nodes/{nodeId}/webhook-endpoint

Required permission: nodes:write. See Authentication.

Path parameters

nodeIdstringRequired

ID of the node in your account. Find it with List nodes.

Deleting the endpoint also removes its delivery history. Use Update webhook endpoint to pause delivery or change the URL while keeping the configuration. A missing endpoint returns 404 webhook_endpoint_not_found.

List webhook deliveries

Read the latest 50 deliveries for your node, newest first.

GET/nodes/{nodeId}/webhook-deliveries

Required permission: nodes:read. See Authentication.

Path parameters

nodeIdstringRequired

ID of the node in your account. Find it with List nodes.

The response wraps records in deliveries. Each record includes id, eventType, payload, status, attemptCount, lastResponseStatus, lastError, createdAt, lastAttemptAt and deliveredAt. See Webhooks for event payload fields.

Use this history to troubleshoot your receiver. Status is pending, retrying, delivered, failed or cancelled. Timestamps use Unix seconds; lastAttemptAt, deliveredAt, lastResponseStatus and lastError may be null.

Attestation

Request fresh evidence of a protected host's boot state and running node bundle before trusting its connection. The response contains an AWS-signed attestation document and the host's TLS certificate. Receiving a successful response does not mean the evidence has been verified; verification happens in your client.

POST/attestation

This is a Nodana protected-host endpoint. Use your node's normal HTTPS URL, such as https://node-a1b2.nodana.app. Attestation and Phoenixd requests use the same URL on the standard HTTPS port, 443.

Authentication: none. Do not send a Phoenixd password, Nodana API key or Authorization header.

JSON body

noncestringRequired

A cryptographically random 32-byte challenge encoded as standard Base64. Generate a new challenge for every request and retain it to verify the response. Send only this field, with Content-Type: application/json.

Response

FieldTypeDescription
certificatestringThe protected host's TLS certificate in PEM format.
attestationDocumentstringThe AWS-signed attestation document, encoded as Base64.
identityobjectThe node identity and connection details covered by the proof.

The document contains boot measurements, a timestamp, your challenge and a signed binding to the certificate, node, owner and bundle identity. Your verifier must check the AWS signature and certificate chain, freshness, challenge, expected identity, approved host measurements and independently approved bundle checksum before trusting the returned certificate or sending credentials.

The identity object contains version (2), hostname, nodeId, nodePublicKey, ownerPublicKey, certificateSha256 and release. Compare its hostname with the URL you requested. If you have saved node or owner public keys, compare those too; an identity supplied by the response alone does not establish that it is your original wallet.

The release object contains releaseSha256, version, phoenixdVersion and stateFormat. Compare releaseSha256 with the canonical manifest checksum you have independently approved. The measured host software checks the installed bundle and running process before reporting this identity.

The signed binding is SHA-256 of nodana-public-tls-v1 followed by a null byte and the canonical JSON encoding of identity (keys sorted, no whitespace). certificateSha256 is the lowercase SHA-256 hex digest of the exact UTF-8 PEM string in certificate. Verify the binding and compare the certificate's leaf with the certificate on your TLS connection.

Keep approved measurements in your client rather than accepting them from the response. Do not trust a certificate merely because it arrived alongside an attestation document. See Security: attestation for what verification establishes.

Errors

StatusErrorAction
400invalid_requestSend a JSON body containing only nonce, without credentials.
400invalid_encodingEncode exactly 32 random bytes as standard Base64.
404node_not_readyCheck the node ID and wait until the node is ready.
429busyWait before requesting new evidence.
503attestation_unavailableRetry later; connection evidence is unavailable.
502node_unavailableRetry later; verification has not succeeded.

Webhooks

Receive an HTTP POST when your Nodana-hosted node receives a payment. Configure one public HTTPS receiver per node to notify your application.

Add your endpoint

  1. Open your node in the dashboard and select Webhooks.
  2. Choose Add endpoint and enter your receiver’s public HTTPS URL.
  3. Copy the signing secret when it is shown and store it in your receiver’s secret settings. It is shown once.
  4. Keep the endpoint enabled to receive notifications.

You can also create the endpoint through the API using a Nodana key with nodes:write. Read, update or delete it using the same node ID.

Handle a payment

Verify webhook authentication before parsing the request. Match nodeId and paymentHash to your saved payment, then check the amount before fulfilling the order. Use Get incoming payment if you need to look up the invoice or confirm its current state.

FieldTypeMeaning
idstringEvent identifier
typestringpayment_received
nodeIdstringNodana ID for the receiving node
paymentHashstringPayment hash as a hexadecimal string
amountSatintegerAmount received in satoshis
amountMsatstringAmount received in millisatoshis, encoded as a decimal string
receivedAtintegerTime received, in Unix seconds
payerNotestringOptional message from the payer
payerKeystringOptional public key identifying the payer

Acknowledge delivery

Return a 2xx response after you have safely recorded the event. Nodana retries failed deliveries, so make processing repeatable: use the event ID or node and payment hash to prevent duplicate fulfilment.

Check recent deliveries or the node’s Webhooks tab when troubleshooting. Confirm that the endpoint is enabled, reachable over HTTPS and returning a successful status. Use incoming payment history to reconcile payments if your receiver was unavailable.

Webhook authentication

Verify the X-Nodana-Signature header before accepting a webhook. Use the signing secret returned when you create the endpoint, or shown when you add it in the dashboard. Store it in your receiver’s secret configuration as NODANA_WEBHOOK_SECRET.

Nodana signs the complete request body with HMAC-SHA256 and sends the signature as a hexadecimal string. Use the entire signing secret as UTF-8 text, including its whsec_ prefix.

Verify a request

  1. Capture the raw request body before JSON parsing.
  2. Calculate its HMAC-SHA256 using your endpoint’s signing secret.
  3. Compare it with X-Nodana-Signature using a constant-time comparison.
  4. Reject a missing or invalid signature. Parse and process the JSON only after verification succeeds.

Use the original request bytes: parsing and reserializing JSON can change the signature. Keep the secret private. If it is lost or exposed, replace the webhook endpoint and configure your receiver with the new signing secret.

After verification, check the node, payment hash and amount against your order, and record fulfilment once. A valid signature does not make a repeated delivery a new payment.

Create BOLT11 invoice

Creates a Bolt11 invoice with a description.

A Bolt11 invoice is a non-reusable, expirable payment request for Lightning, well suited for a retail payment flow. It can only be paid once.

POST/createinvoice

Authentication: full or limited Phoenixd password. See Authentication.

Form parameters

descriptionstringOptional

Invoice description, up to 128 characters. Supply either description or descriptionHash.

descriptionHashstringOptional

SHA-256 hash of the description, as an alternative to description.

amountSatintegerOptional

Amount requested in satoshis. Omit to allow the payer to choose the amount.

expirySecondsintegerOptional

Invoice lifetime in seconds. Defaults to 3600 (one hour).

externalIdstringOptional

Your order or payment reference. Use it when looking up incoming invoices.

webhookUrlstringOptional

Additional callback URL for this invoice, called directly by Phoenixd. Configure Nodana webhooks for notifications delivered by Nodana.

Send parameters as application/x-www-form-urlencoded.

Create BOLT12 offer

Creates a Bolt12 offer with an optional description and amount.

An offer is a static and reusable payment request that does not expire. It can be paid many times. It's well suited for donations or tips.

Note: a getoffer call is also available but it is deprecated. This getoffer endpoint returns an offer, but always the same one. createoffer should be used instead.

POST/createoffer

Authentication: full or limited Phoenixd password. See Authentication.

Form parameters

descriptionstringOptional

Offer description, up to 128 characters. Required when amountSat is provided.

amountSatintegerOptional

Amount requested in satoshis. Omit to allow the payer to choose the amount.

Send parameters as application/x-www-form-urlencoded.

Get Lightning address

Gets a BIP-353 Lightning address from the LSP. Only works if you have a channel.

Note you can also use third-party services or self-host the address.

GET/getlnaddress

Authentication: full or limited Phoenixd password. See Authentication.

Get swap-in address

Gets an on-chain address to swap on-chain funds into Lightning.

GET/getswapinaddress

Authentication: full or limited Phoenixd password. See Authentication.

Pay BOLT11 invoice

Pays a BOLT11 Lightning invoice. A 0.4% fee applies. Response includes the internal paymentId for that payment.

POST/payinvoice

Authentication: full Phoenixd password. See Authentication.

Form parameters

invoicestringRequired

BOLT11 invoice to pay.

amountSatintegerOptional

Amount in satoshis. If omitted, uses the amount in the payment request. Supply amountSat or sendAll for an amountless request.

sendAllbooleanOptional

Send the wallet balance when there is a single channel. Mutually exclusive with amountSat.

Send parameters as application/x-www-form-urlencoded.

Payment attempts can return HTTP 200 with type: "payment_failed". Check the result before treating the payment as sent. A successful result has type: "payment_sent".

Pay BOLT12 offer

Pays a BOLT12 Lightning offer. A 0.4% fee applies. Response includes the internal paymentId for that payment.

POST/payoffer

Authentication: full Phoenixd password. See Authentication.

Form parameters

offerstringRequired

BOLT12 offer to pay.

amountSatintegerOptional

Amount in satoshis. If omitted, uses the amount in the payment request. Supply amountSat or sendAll for an amountless request.

sendAllbooleanOptional

Send the wallet balance when there is a single channel. Mutually exclusive with amountSat.

messagestringOptional

Optional message for the recipient; the receiving service may restrict its length.

Send parameters as application/x-www-form-urlencoded.

Payment attempts can return HTTP 200 with type: "payment_failed". Check the result before treating the payment as sent. A successful result has type: "payment_sent".

Pay Lightning address

Pays an email-like Lightning address, either based on BIP-353 or LNURL. A 0.4% fee applies. Response includes the internal paymentId for that payment.

POST/paylnaddress

Authentication: full Phoenixd password. See Authentication.

Form parameters

addressstringRequired

Lightning address using BIP-353 or LNURL.

amountSatintegerOptional

Amount in satoshis. Supply amountSat or sendAll; Lightning addresses do not supply a default amount.

sendAllbooleanOptional

Send the wallet balance when there is a single channel. Mutually exclusive with amountSat.

messagestringOptional

Optional message for the recipient; the receiving service may restrict its length.

Send parameters as application/x-www-form-urlencoded.

Payment attempts can return HTTP 200 with type: "payment_failed". Check the result before treating the payment as sent. A successful result has type: "payment_sent".

Pay on-chain

Sends part of your current balance to a Bitcoin address. The spliced channel is not closed and remains active. Returns the transaction id if the splice was successful.

POST/sendtoaddress

Authentication: full Phoenixd password. See Authentication.

Form parameters

amountSatintegerRequired

Amount to send in satoshis.

addressstringRequired

Destination Bitcoin address.

feerateSatByteintegerRequired

Fee rate in satoshis per virtual byte.

Send parameters as application/x-www-form-urlencoded.

The response is plain text. Check that it contains a transaction ID: an unsuccessful action can return an explanatory message with HTTP 200.

Bump fee

Makes all your unconfirmed transactions use a higher fee rate, using CPFP. Returns the ID of the child transaction.

POST/bumpfee

Authentication: full Phoenixd password. See Authentication.

Form parameters

feerateSatByteintegerRequired

Fee rate in satoshis per virtual byte.

Send parameters as application/x-www-form-urlencoded.

The response is plain text. Check that it contains a transaction ID: an unsuccessful action can return an explanatory message with HTTP 200.

List incoming payments

Lists incoming payments.

GET/payments/incoming

Authentication: full or limited Phoenixd password. See Authentication.

Query parameters

fromintegerOptional

Start time in Unix milliseconds. Defaults to 0.

tointegerOptional

End time in Unix milliseconds. Defaults to now.

limitintegerOptional

Number of payments to return. Defaults to 20.

offsetintegerOptional

Pagination offset. Defaults to 0.

allbooleanOptional

Include unpaid invoices.

externalIdstringOptional

Only return payments with this external ID.

Get incoming payment

Look up an incoming payment by its payment hash. Check isPaid and receivedSat before fulfilling an order. isExpired indicates that an unpaid invoice can no longer be paid.

GET/payments/incoming/{paymentHash}

Authentication: full or limited Phoenixd password. See Authentication.

Path parameters

paymentHashstringRequired

Payment hash as a hexadecimal string.

List outgoing payments

Lists outgoing payments.

GET/payments/outgoing

Authentication: full or limited Phoenixd password. See Authentication.

Query parameters

fromintegerOptional

Start time in Unix milliseconds. Defaults to 0.

tointegerOptional

End time in Unix milliseconds. Defaults to now.

limitintegerOptional

Number of payments to return. Defaults to 20.

offsetintegerOptional

Pagination offset. Defaults to 0.

allbooleanOptional

Include failed payments.

Get outgoing payment

Look up an outgoing payment by its internal payment ID or payment hash. Use the ID returned by the payment request. Check isPaid and completedAt when reconciling an interrupted request.

GET/payments/outgoing/{paymentId}
GET/payments/outgoingbyhash/{paymentHash}

Authentication: full or limited Phoenixd password. See Authentication.

Path parameters

paymentIdstringRequired

Internal payment UUID.

paymentHashstringOptional

Payment hash for the alternative outgoingbyhash route.

For outgoing Lightning payments, isPaid: true with completedAt indicates success. isPaid: false with no completedAt is pending; isPaid: false with completedAt indicates failure.

CSV export

Exports your successful payments history in a CSV file. Returns the path of the generated file on your file system.

The resulting CSV allows precise tracking of the balance and fee credit, and shows the split between mining and service fees:

  • balance: sum of all amount_msat;

  • fee credit: sum of all fee_credit_msat.

The returned path is on the machine or container running Phoenixd. Retrieve the file there; the response body is a message containing its path.

POST/export

Authentication: full or limited Phoenixd password. See Authentication.

Query parameters

fromintegerOptional

Start time in Unix milliseconds. Defaults to 0.

tointegerOptional

End time in Unix milliseconds. Defaults to now.

Get node info

Read the Lightning node ID and a compact summary of its channels. Channel balances, inbound liquidity and capacity are expressed in satoshis.

GET/getinfo

Authentication: full or limited Phoenixd password. See Authentication.

Get balance

Read the available balance and fee credit, both in satoshis.

GET/getbalance

Authentication: full or limited Phoenixd password. See Authentication.

List channels

Read detailed channel state. For a compact channel summary, use Get node info. The example shows an excerpt; available fields depend on channel state.

GET/listchannels

Authentication: full or limited Phoenixd password. See Authentication.

Close channel

Closes a given channel, and send all funds to an on-chain address. Returns the ID of the closing transaction.

Attention: closing a channel is final, it cannot be cancelled.

POST/closechannel

Authentication: full Phoenixd password. See Authentication.

Form parameters

channelIdstringRequired

ID of the channel to close.

addressstringRequired

Bitcoin address to receive the channel balance.

feerateSatByteintegerRequired

Fee rate in satoshis per virtual byte.

Send parameters as application/x-www-form-urlencoded.

The response is plain text. An unsuccessful action can return an explanatory message with HTTP 200; confirm the closing transaction ID before reporting success.

Decode invoice

POST/decodeinvoice

Authentication: full or limited Phoenixd password. See Authentication.

Form parameters

invoicestringRequired

BOLT11 invoice to decode.

Send parameters as application/x-www-form-urlencoded.

Decode offer

POST/decodeoffer

Authentication: full or limited Phoenixd password. See Authentication.

Form parameters

offerstringRequired

BOLT12 offer to decode.

Send parameters as application/x-www-form-urlencoded.

Estimate liquidity fees

Estimates a liquidity fee for a given amount. Note that it depends on the current mining feerate, which is volatile. The estimate returned is the full cost and does not take into account any fee credit you may have.

GET/estimateliquidityfees

Authentication: full or limited Phoenixd password. See Authentication.

Query parameters

amountSatintegerRequired

Liquidity amount in satoshis.

LNURL Pay

Pays a LNURL-pay resource. Note that the service may apply restrictions on the amount to pay or the message -- the lnurl-pay flow is usually interactive.

POST/lnurlpay

Authentication: full Phoenixd password. See Authentication.

Form parameters

lnurlstringRequired

LNURL-pay resource.

amountSatintegerOptional

Amount to pay in satoshis. If omitted with sendAll unset, uses the minimum accepted by the service.

sendAllbooleanOptional

Send the wallet balance when there is a single channel. Mutually exclusive with amountSat.

messagestringOptional

Optional message for the recipient; the receiving service may restrict its length.

Send parameters as application/x-www-form-urlencoded.

Payment attempts can return type: "payment_failed" with HTTP 200. Check the returned type and reconcile uncertain attempts using Get outgoing payment.

LNURL Withdraw

Withdraws funds from a LNURL service. Phoenixd will withdraw the maximum amount authorized by the service.

POST/lnurlwithdraw

Authentication: full or limited Phoenixd password. See Authentication.

Form parameters

lnurlstringRequired

LNURL-withdraw resource.

Send parameters as application/x-www-form-urlencoded.

LNURL Auth

Authenticates a LNURL-auth resource to allow an action on a remote service. See LUD-04 for details.

Note: The key used to sign is derived from the wallet's key (derivation depends on the lnurl service's domain). If you have different users using the same phoenixd instance, do not let them use this or they will share the same signature and pubkey!

POST/lnurlauth

Authentication: full Phoenixd password. See Authentication.

Form parameters

lnurlstringRequired

LNURL-auth resource.

Send parameters as application/x-www-form-urlencoded.

WebSocket

WS /websocket

Subscribe to received-payment events. Use the full or limited Phoenixd password. For an HTTPS node URL, connect with wss://; a daemon on the same machine uses ws://127.0.0.1:9740/websocket.

Authentication

Phoenixd accepts Basic authentication on the WebSocket handshake or authentication through Sec-WebSocket-Protocol. The example uses a server-side client with Basic authentication and an empty username. Keep the password on your backend.

Events

Each JSON message has type: "payment_received", the payment hash and the amount in satoshis. Events can include externalId for an invoice or payerKey and payerNote for an offer. Match the payment hash or external ID to your saved order.

After reconnecting, use incoming payment history to reconcile receipts. Confirm the payment and expected amount before fulfilment, and record fulfilment once for each order.