Hypawave Docs
Hypawave Agent API
Complete reference for the programmable Bitcoin settlement API
Quick Start
Get from zero to your first payment request in 5 steps.
- Create an API key — Open the menu, go to API Keys, create a live key, and copy it immediately. The raw key is shown only once.
- Create a payment request —
POST /api/agent/create-invoicewith your key in theAuthorizationheader. Specify amount, currency, and client details.payment_destinationdefaults to your API key owner's savedlightning_address; pass it explicitly only to override (marketplace, multi-wallet, or pass-through flows). - Send to payer agent — The response includes
invoice_id,access_token, andinstructions_url. Send the payment payload to the payer agent via any channel (HTTP, MCP, A2A, etc.). Theinstructions_urlpoints to machine-readable settlement instructions so the payer agent can complete the flow without prior Hypawave knowledge. The response also includespayment_url— a browser-based payment page. Use it when the payer pays via a browser. - Payer agent confirms settlement — The payer agent calls
GET /api/paystream-cb?token={access_token}to fetch the Lightning bolt11, pays it using their own programmable Lightning infrastructure (LND, CLN, Alby API, LNbits, NWC, etc.), then submits thepayment_hashandpreimagetoPOST /api/invoice/{id}/confirm. A service fee is recorded (seeGET /api/public-settingsfor currentfee_percent). - Attachments unlock (if any) — Encrypted files become available. Retrieve the decryption key via
GET /api/get-key.
Minimal curl Example
Note: First payment request is free — balance starts at zero. After payment settles, a service fee is recorded (see GET /api/public-settings for current fee_percent). When balance goes negative, call POST /api/agent/topup (empty body) to mint a bolt11 for exactly the amount owed and settle fees. To settle programmatically, the agent needs outbound Lightning payment capability (a funded wallet that can pay bolt11s). Otherwise, settle fees via the dashboard.
TypeScript SDK
The fastest way to integrate with Hypawave. Zero dependencies, full TypeScript types, works in Node.js and any modern runtime.
Install
Open source under MIT — source code at github.com/hypawave/sdk.
Quick Example
Available Methods
| Method | Description |
|---|---|
createInvoice(params) | Create a payment request |
getBolt11(accessToken) | Fetch creator-issued Lightning bolt11 |
confirmPayment(invoiceId, params) | Confirm settlement with preimage |
getPaymentPayload(params, response) | Build self-describing payload for agent interop |
getBalance(currency?) | Check settlement balance |
topup() | Settle outstanding fees via Lightning |
getUnlockStatus(invoiceIds) | Check settlement status |
getInvoiceFiles(invoiceIds) | Get file metadata for invoices |
getDownloadUrl(fileId) | Generate signed download URL |
getKey(fileId) | Retrieve encryption key for a file |
getReceipt(invoiceId) | Get creator receipt for settled invoice |
getPayerReceipt(invoiceId, preimage) | Get payer receipt for settled invoice |
getSettings() | Fetch current platform configuration |
waitForSettlement(invoiceId, opts?) | Poll until settled (with timeout) |
getUploadUrl(params) | Get presigned URL for file upload |
storeFile(params) | Store encrypted file metadata |
storeFileKey(params) | Store encryption key for file |
listInvoices(params?) | List your payment requests |
Error Handling
CJS + ESM + TypeScript — The SDK ships as CommonJS, ES Modules, and full type declarations. Works with any bundler, Node.js, Bun, or Deno.
Overview
The Hypawave Agent API is the programmable interface to Bitcoin-native settlement. Developers and agents create payment requests, attach encrypted data, check balances, and settle outstanding fees — all through API keys and the SDK.
Who is it for
- AI agents needing to pay/sell data/compute/services autonomously
- Developers building agent-to-agent workflows
- Automated systems
- Any software needing programmable non-custodial Bitcoin settlement
What can it do
- Create payment requests with fiat→BTC conversion
- Attach encrypted files/links/data
- Gate access to content
- Check balance in sats and fiat
- Settle outstanding fees via Lightning (fee-settlement only — balance never goes above zero)
- API keys provisioned from menu
Bigger Picture
Settlement layer for autonomous commerce. Hypawave Protocol handles authorization and settlement verification. Bitcoin is the rail.
Base URL
Note: The Agent API is powered by the Hypawave Protocol — same encryption, settlement verification, and unlock logic across all paths.
Authentication
All Agent API requests require a Bearer token in the Authorization header. No cookies or CSRF.
Header
Key Formats
| Format | Mode |
|---|---|
sk_test_<base64url> | Test mode |
sk_live_<base64url> | Live mode |
Security
- Keys hashed SHA-256 before storage
- Raw key shown once at creation
- Revoked keys rejected immediately
- Every request logged for audit
Key Management
Keys are created and revoked from the API Keys section in the menu. Requires login.
POST /api/agent/create-key
Create a new API key.
Request body:
Response:
POST /api/agent/revoke-key
Revoke an existing API key.
Request body:
Rate Limit
5 requests/hour per IP, 3/hour per identity.
Endpoints
POST /api/agent/create-invoice
Create a payment request.
Request body fields:
| Field | Description |
|---|---|
client_email | Payer's email address |
client_first_name | Payer's first name |
client_last_name | Payer's last name |
amount | Payment amount |
currency | Currency code (40+ supported) |
due_date | Due date |
payment_destination | Lightning Address or LNURL-pay URL. Optional — defaults to the API key owner's saved lightning_address. Override per-call for marketplace routing, multi-wallet owners, or pass-through flows. |
description | Description text |
company_name | Company name |
expires_in | Expiry: 1h, 24h, 7d, or null |
creator_first_name | Creator's first name |
creator_last_name | Creator's last name |
Response (201):
| Field | Description |
|---|---|
ok | Success boolean |
invoice_id | Invoice identifier |
access_token | Token for payment flow |
payment_url | Browser-based payment page |
instructions_url | Settlement instructions for payer agents (llms.txt) |
stream_id | Stream identifier |
amount | Amount in specified currency |
currency | Currency code |
sats | Amount in satoshis |
btc_usd_rate | BTC/USD rate used |
expires_at | Expiration timestamp |
Limits: Amount limits and fee percentage are configurable — query GET /api/public-settings for current values (min_invoice_usd, max_invoice_usd, fee_percent). 40+ currencies, expiry 1h/24h/7d/null. Creating invoices requires a non-negative balance — a service fee is deducted post-settlement.
GET /api/agent/balance
Check balance.
Query: ?currency=USD
Response (200):
| Field | Description |
|---|---|
available_sats | Balance in satoshis |
fiat_equivalent | Balance in requested currency |
currency | Currency code |
btc_price | Current BTC price |
has_outstanding_fee | Whether a fee is pending |
POST /api/agent/topup
Mint a Lightning invoice for exactly the amount owed in outstanding settlement fees.
Fee-settlement only. The server mints a bolt11 for exactly -available_sats. Callers cannot specify an amount. If the balance is already ≥ 0, the request is rejected with topup_not_needed. Hypawave never pre-funds balances.
Request body:
Response (200):
| Field | Description |
|---|---|
ok | Success boolean |
bolt11 | Lightning invoice for the exact owed amount |
payment_hash | Payment hash |
amount_sats | Exact owed amount in satoshis |
expires_at | Invoice expiration |
reused | true if an existing pending invoice was returned (double-click protection) |
400 errors: topup_not_needed (balance is already ≥ 0; response includes available_sats).
GET /api/paystream-cb
Fetch the creator-issued Lightning bolt11 for payment. Used by agent/developer payers to get the invoice to pay.
Query: ?token={access_token}
Response (200):
| Field | Description |
|---|---|
pr | Lightning bolt11 invoice (pay this with your Lightning node) |
routes | Routing hints (typically empty) |
402 errors: activation_pending (accountless invoices only — activation fee has not settled yet).
POST /api/invoice/{id}/confirm
Confirm invoice payment by submitting the Lightning preimage. No API key or webhook secret required — authorization is cryptographic proof bound to the specific invoice.
Request body:
Response (200):
| Field | Description |
|---|---|
ok | Success boolean |
already_settled | true if the invoice was already settled (idempotent) |
Errors: 400 missing_proof, invalid_payment_hash, invalid_preimage, preimage_hash_mismatch, no_matching_attempt. 404 invoice_not_found, transaction_not_found. 409 payment_hash_replay.
Requirement: This endpoint requires programmable Lightning infrastructure (LND, CLN, Alby API, LNbits, NWC, etc.) that exposes the payment_hash and preimage after successful payment. Consumer wallets (Wallet of Satoshi, Phoenix, etc.) do not reliably expose the preimage.
Pubkey Authentication
Accountless agents authenticate using a secp256k1 keypair instead of API keys. No account creation, no login, no browser required. The agent's compressed public key is its identity.
Two primitives, one identity
Accountless agents have two distinct ways to transact. Offers are persistent, reusable payment endpoints — any agent or human can pay them at any time, designed for standing services with repeating payments. One-time custom payments are single-use invoices with optional encrypted file attachments, scoped to a single payer — the same model as the Agent API but without requiring an account. Both use the same keypair auth and the same prepaid balance.
Header Format
| Header | Type | Description |
|---|---|---|
x-pubkey | string | Compressed public key (66-char hex) |
x-signature | string | secp256k1 signature over the payload hash (hex) |
x-signed-payload-hash | string | SHA-256 hash of the raw request body (hex) |
How It Works
- Hash the request body — Compute SHA-256 of the raw JSON body to produce a 32-byte payload hash.
- Sign the hash — Sign the payload hash with your secp256k1 private key to produce a DER-encoded signature.
- Set headers — Include x-pubkey (your compressed public key), x-signature (the signature), and x-signed-payload-hash (the hex hash) on the request.
- Auto-identity — On first request, Hypawave auto-creates a pubkey-only identity. No registration needed — the public key IS the identity.
GET Requests: GET endpoints (balance, list) have no request body. Sign an empty string "" instead — compute sha256("") and use that as both the value you sign and the x-signed-payload-hash header.
Signing Example (JavaScript)
Account-Based vs. Pubkey Auth
| Property | API Key (Bearer) | Pubkey Auth |
|---|---|---|
| Identity | Supabase auth user + identity row | Pubkey-only identity (no auth user) |
| Setup | Sign up, log in, create API key | Generate keypair — done |
| Fee model | Postpaid (service fee deducted from balance on settlement) | Upfront (pay activation bolt11 to activate; no balance writes) |
| Endpoints | /api/agent/* endpoints | /api/offers/* endpoints |
| Use case | Humans + managed agents | Autonomous agents, accountless access |
Pubkey auth is designed for fully autonomous agents. The agent's private key never leaves the agent's runtime. Hypawave only ever sees the public key and signatures.
Persistent Identity & History
Your keypair is your identity. On first contact, Hypawave auto-creates an identity row linked to your public key. As long as you sign with the same private key, you can query your full history at any time:
GET /api/offers/list-invoices— all invoices you created (Path 3a)GET /api/offers/list-payments— payment history per offer (Path 3b)POST /api/offers/payment-intent/{id}/receipt— settlement receiptPOST /api/offers/payment-intent/{id}/status— payment intent status
Lose the private key, lose access to history. There is no recovery mechanism — the keypair is the sole credential.
Offers (Accountless Agents)
Offers are persistent, reusable payment endpoints — unlike one-off invoices, an offer lives until the creator deactivates it and any agent or human can pay it at any time. Each payment spawns an independent payment intent. For single-payer, one-time flows, see One-Time Custom Payments.
Upfront activation fee model
Accountless offers are non-custodial on both sides: you pay Hypawave's service fee upfront (never postpaid), and payers pay you directly over Lightning. POST /api/offers returns a top-level activation sibling containing a Hypawave-issued fee_bolt11. Pay it to activate the offer. The offer is inert until that fee settles and stays payable for the requested activation_window (default 30d, bounds [1d, 365d]). When the window elapses, call POST /api/offers/{id}/renew to mint a fresh activation bolt11.
Fee policy: max(min_fee_sats, floor(declared_price_sats * fee_percent / 100)). See GET /api/public-settings for current values. For fiat offers, declared_price_sats is locked at mint time using a fresh BTC price. Offer terms are snapshotted into terms_hash; editing them after activation surfaces 409 terms_changed at pay time — revert or /renew.
POST /api/offers/{id}/renew
Mint a fresh activation fee bolt11 to extend or resume service on an accountless offer. Creator-only (your pubkey must match the offer's creator_pubkey). Returns an activation object in the same shape as create.
Behavior: an existing pending bolt11 is returned unchanged with reused: true (retry-safe). An expired pending row is lazy-expired and a fresh one is minted. If the current window is still active, the endpoint returns 400 activation_not_needed with window_end so you can decide when to renew.
GET /api/offers/list
List the calling agent's own offers. Useful for state recovery and idempotency — check for an existing active offer before creating a duplicate. Filter by ?status= (active, deactivated, or exhausted). Defaults to active. Capped at 100 results.
GET /api/offers/list-invoices
List all invoices the identity created — covers both one-time custom payments and offer-triggered invoices. Supports ?status=paid|not_paid|expired, ?limit= (max 50), and ?offset=.
GET /api/offers/list-payments
List all payment intents received against the identity's offers, with full settlement state. Use for auditing, reconciliation, and crash recovery. Supports ?status=pending|settled|failed, ?offer_id=, ?limit= (max 50), and ?offset=.
POST /api/offers
Create a new offer. Account-based creators require non-negative balance; accountless creators pay an upfront activation fee instead. Supports pubkey auth or Bearer token. Set max_payments to limit payments (e.g. 1 for single-use delivery). Omit or set to null for unlimited. payment_destination is required — the creator's Lightning Address or LNURL-pay URL where payers will be sent at pay time.
Required fields:
| Field | Type | Description |
|---|---|---|
amount | number | Price per payment |
pricing_type | string | 'sats' or 'fiat' |
description | string | What the offer provides |
payment_destination | string | Creator's Lightning Address or LNURL-pay URL |
signed_payload_hash | string | SHA-256 of body (hex) |
signature | string | secp256k1 signature (hex) |
Optional fields:
| Field | Type | Description |
|---|---|---|
currency | string | Fiat code (if pricing_type='fiat') |
execution_webhook | string | HTTPS URL to call on settlement |
max_payments | integer|null | Payment limit (null = unlimited) |
metadata | object | Arbitrary key-value metadata |
activation_window | string | "Nd" format, default "30d", bounds [1d, 365d] |
GET /api/offers/{id}
Read an offer. Public endpoint — no authentication required. Returns offer details including payment limits and file attachment info.
DELETE /api/offers/{id}
Deactivate an offer. Only the creator (matching pubkey) can deactivate it. Existing settled payment intents are not affected. Returns 409 if already deactivated.
POST /api/offers/{id}/pay
Pay an offer. Hypawave fetches a fresh Lightning invoice from the creator's payment_destination endpoint and returns it along with a payer_secret. The payer pays the bolt11 directly to the creator — Hypawave never receives the principal. No authentication required — anyone can pay.
Save the payer_secret immediately. It is required to submit the preimage proof via the confirm endpoint and to check status / retrieve file keys after settlement. It is shown only once and stored hashed.
POST /api/offers/payment-intent/{id}/confirm
Submit settlement proof for a direct-pay offer payment. After paying with your programmable Lightning infrastructure (LND, CLN, Alby API, LNbits, NWC, etc.), POST the preimage and payer_secret. Hypawave verifies SHA256(preimage) === payment_hash and authorizes the intent. Idempotent: repeated calls return already_settled: true.
Errors: 400 invalid_preimage, 400 missing_payer_secret, 400 preimage_mismatch, 401 unauthorized, 404 payment_intent_not_found.
POST /api/offers/upload-url
Get a presigned URL to upload an encrypted file for an offer. URL expires after 1 hour.
POST /api/offers/store-file
Link uploaded file metadata to an offer. Only the offer creator can call this.
POST /api/offers/store-file-key
Store the wrapped encryption key for a file attached to an offer.
GET /api/offers/payment-intent/{id}/status
Check payment intent status. Requires the payer_secret returned at pay time. After settlement, includes a claim_token for file key retrieval.
GET /api/offers/payment-intent/{id}/file-key
Retrieve wrapped decryption keys for all files attached to a settled payment intent. Requires a valid claim_token or the Lightning preimage as proof of payment.
POST /api/offers/payment-intent/{id}/download-url
Generate a time-limited presigned download URL (5 min) for a single encrypted offer file. Authenticated via claim_token or preimage in the request body.
GET /api/offers/payment-intent/{id}/receipt
Retrieve a structured JSON receipt for a settled payment intent. Authenticated via payer_secret.
Pricing Types
| Type | Behavior | Use case |
|---|---|---|
sats | Fixed satoshi amount. Invoice is created for exactly this amount. | Machine-to-machine payments |
fiat | Fiat-denominated. Converted to sats at current BTC price when payment intent is created. | Services priced in USD/EUR etc. |
Offers are designed for autonomous agents. The creator sets up an offer once, and any number of payers can pay it independently. Each payment creates a separate payment intent with a snapshot of the offer terms at the time of payment. Offers support encrypted file attachments — attach files at creation, and payers retrieve decryption keys after settlement.
One-Time Custom Payments
The second primitive available to accountless agents. One-time custom payments are single-use invoices targeted at a specific payer — the same model as the Agent API's create-invoice, but authenticated with a secp256k1 keypair instead of a Bearer token. All the same fields are supported: expiry, currencies, client info, creator branding, and optional encrypted file attachments. Like offers, the creator pays an upfront activation fee at creation (see GET /api/public-settings for current fee_percent and min_fee_sats) — no balance, no postpaid debt.
Flow
- Create the invoice — POST /api/offers/create-invoice with pubkey headers. Specify all client and payment details. Response returns invoice_id, access_token, payment_url, AND a top-level activation object containing fee_bolt11 — an upfront activation fee you must pay before the invoice becomes payable.
- Pay the activation fee — Pay activation.fee_bolt11 using any Lightning wallet. The fee is computed from the declared invoice amount (see GET /api/public-settings for fee_percent). Until this settles, the payment_url returns 402 activation_pending.
- (Optional) Encrypt a file locally — AES-256-GCM recommended. Generate a random key and IV. Upload the encrypted blob to storage and note the objectKey.
- (Optional) Store invoice file — POST /api/offers/store-invoice-file with the invoice_id, objectKey, IV, and key hash.
- (Optional) Store decryption key — POST /api/offers/invoice-file-key with the invoice_file_id and base64-encoded encryption key.
- Share and poll — Share the payment_url with the payer. Poll settlement status via POST /api/get-unlock-status with pubkey headers and { invoice_ids: [42] }. After Lightning settlement, the protocol releases the file key automatically.
Endpoints
POST /api/offers/create-invoice
Auth: Pubkey headers. Mints a Hypawave-issued activation fee bolt11 returned in the activation response field. The invoice is inert until the creator pays that fee.
POST /api/offers/store-invoice-file
Auth: Pubkey headers. Register an encrypted file attachment against an invoice you created.
POST /api/offers/invoice-file-key
Auth: Pubkey headers. Store the base64-encoded decryption key for a file attached to your invoice.
POST /api/get-unlock-status
Auth: Pubkey headers, Bearer token, or session cookie. Poll settlement status for your invoices.
Accountless agents pay an upfront activation fee at creation — no balance, no postpaid debt. Each invoice has its own activation lifecycle: pay the activation.fee_bolt11, and the invoice becomes payable. To retrieve history, use GET /api/offers/list-invoices.
Agent-to-Agent Walkthrough
Complete end-to-end walkthrough of two autonomous agents transacting through the offers system. No accounts, no API keys, no browser, no human in the loop.
The Flow
- Agent A generates a keypair — Agent A generates a secp256k1 private key and derives its compressed public key. This public key is the agent's permanent identity.
- Agent A creates an offer — POST /api/offers with amount, pricing_type, description, payment_destination (Agent A's Lightning Address or LNURL-pay URL), an optional execution_webhook URL, and an optional activation_window ("30d" default, bounds [1d, 365d]). The response includes a top-level activation object containing a Hypawave-issued fee_bolt11.
- Agent A pays the activation fee — Pay activation.fee_bolt11 using any Lightning wallet. Fee is computed from the declared price (see GET /api/public-settings for fee_percent). Once the fee settles, the offer becomes payable for the requested activation_window. Extend or resume service later via POST /api/offers/{id}/renew.
- Agent B discovers the offer — GET /api/offers/{id} returns the offer details. Agent B evaluates whether to pay.
- Agent B pays the offer — POST /api/offers/{id}/pay returns a creator-issued Lightning invoice and a payer_secret. The route enforces the activation gate — returns 402 offer_inactive if the activation window has elapsed, or 409 terms_changed if Agent A edited the offer's terms after activation. Agent B saves the payer_secret and pays the invoice directly to Agent A.
- Agent B confirms settlement — After Agent B's wallet reveals the preimage, Agent B POSTs {preimage, payer_secret} to /api/offers/payment-intent/{id}/confirm. Hypawave verifies SHA256(preimage) == payment_hash and POSTs to Agent A's execution_webhook. No fee deduction at settlement — the fee was already paid upfront via activation.
- Agent B retrieves its receipt — GET /api/offers/payment-intent/{id}/receipt?secret={payer_secret} returns a structured JSON receipt — machine-readable proof of the transaction.
Complete Example (JavaScript)
Quick Reference (curl)
No accounts. No API keys. No browser. Agent A exists as a public key. Agent B doesn't even need an identity — it just pays a Lightning invoice. Settlement triggers deterministic execution via webhook. The entire flow is machine-native.
With File Delivery
The same flow extends to encrypted file delivery. Agent A attaches encrypted files to the offer. Agent B pays, then retrieves the decryption keys after settlement.
- Agent A creates offer with file — Agent A creates an offer (optionally with max_payments: 1 for single-use delivery), then attaches an encrypted file via upload-url, store-file, and store-file-key.
- Agent B discovers and pays — Agent B reads the offer (has_files: true, file_count: 1), then calls POST /api/offers/{id}/pay. Saves the payer_secret and pays the creator-issued Lightning invoice directly to Agent A.
- Agent B confirms settlement — Agent B POSTs {preimage, payer_secret} to /api/offers/payment-intent/{id}/confirm.
- Agent B checks status — Agent B calls GET /api/offers/payment-intent/{id}/status?secret=... On settlement, the response includes a claim_token.
- Agent B retrieves file keys — Agent B calls GET /api/offers/payment-intent/{id}/file-key?claim_token=... to get the wrapped decryption keys.
- Agent B downloads encrypted files — For each file, POST /api/offers/payment-intent/{id}/download-url with {offer_file_id, claim_token}. Returns a time-limited presigned URL (5 min).
- Agent B retrieves its receipt — GET /api/offers/payment-intent/{id}/receipt?secret={payer_secret} returns a structured JSON receipt.
- Agent B decrypts locally — Agent B fetches the encrypted blob, unwraps the encryption key, and decrypts. Payment was the authorization.
Webhooks & Callbacks
Hypawave uses polling, not push webhooks.
How Payment Confirmation Works
Principal payments (buyer → creator) are non-custodial and direct. Settlement is confirmed by cryptographic proof — the payer submits the Lightning preimage to Hypawave:
- Invoices (Paths 2/3a): Payer calls
POST /api/invoice/{id}/confirmwith{payment_hash, preimage}. Hypawave verifies SHA256(preimage) == payment_hash and matches against a recorded payment attempt. - Offers (Path 3b): Payer calls
POST /api/offers/payment-intent/{id}/confirmwith{preimage, payer_secret}. - Trusted integrations: Server-to-server settlement via
POST /api/wallet-webhook(requiresWALLET_WEBHOOK_SECRET).
Topup and fee payments are confirmed via an LNbits webhook (secret URL token + server-side API verification). All webhooks are internal infrastructure — agents do not receive push notifications and should poll /api/get-unlock-status or use the SDK's waitForSettlement().
Polling
POST /api/get-unlock-status
Request:
Response:
Polling Strategy
- Every 3–5 seconds
- Exponential backoff after 2 minutes
- Stop after expiry
- Check balance for fee
Polling with Backoff (JavaScript)
Key Retrieval
GET /api/get-key?invoice_file_id=...
Response:
One-time atomic release. 403 key_already_released on repeat. Payment gates access, not identity.
Note: Push webhooks not yet supported, contact for early access.
File Attachments (Advanced)
Why
Enable agents to exchange data as payment-gated transactions. Agent-to-agent commerce foundation.
What Can Be Attached
Any data — files, links, structured metadata, API responses. Links encoded as bytes and encrypted like files.
Flow
- Encrypt locally (AES-256-GCM)
- Upload encrypted blob
POST /api/store-invoice-filePOST /api/store-file-keyGET /api/get-keyafter payment
Auth
Same Bearer token, no CSRF for agents.
Endpoints
| Endpoint | Purpose |
|---|---|
POST /api/store-invoice-file | Store file metadata |
POST /api/store-file-key | Store wrapped encryption key |
POST /api/get-invoice-files | List files for an invoice (Bearer, session, or access_token in body) |
POST /api/generate-download-url | Generate presigned download URL for encrypted file (5 min expiry) |
POST /api/get-unlock-status | Poll unlock status |
GET /api/get-key | Retrieve decryption key (Bearer, session, or access_token query param) |
Ownership Rules
- Only creator can store metadata/keys
- Agents list only their own files
- Key retrieval requires: (1) valid
invoice_file_id, (2) settlement proof recorded for the parent invoice, (3) key not previously claimed. All three conditions must be met. Payment is the authorization — no identity check. - Keys released once via atomic claim
Note: Hypawave never sees plaintext, stores opaque blobs and wrapped keys.
Test vs Live Mode
| Mode | Prefix | Description |
|---|---|---|
| Test | sk_test_... | For dev/testing, same API, marked in audit logs |
| Live | sk_live_... | For production, real Lightning payments |
Both modes hit same endpoints and create real DB records. Test mode filters in audit logs.
Rate Limits
Rate limits are per identity (not per IP). Rate limits do not affect settlement or unlock logic — only API request throughput.
| Resource | Limit |
|---|---|
| API requests | 30/minute |
| Key creation (per IP) | 5/hour |
| Key creation (per identity) | 3/hour |
| Payment requests | 50/24 hours |
Returns 429 with rate_limit_exceeded.
Error Reference
Auth Errors
| Error Code | HTTP Status |
|---|---|
missing_auth | 401 |
invalid_key_format | 401 |
invalid_api_key | 401 |
api_key_revoked | 401 |
Payment Request Errors
| Error Code | HTTP Status |
|---|---|
validation_error | 400 |
amount_below_minimum | 400 |
amount_above_maximum | 400 |
invalid_payment_destination | 400 |
invalid_payment_destination_domain | 400 |
invalid_currency | 400 |
negative_balance | 402 — Returned when attempting to create a new payment request while balance < 0. Does not affect settlement or unlock of already settled payments. |
daily_limit | 429 |
rate_limit_exceeded | 429 |
price_feed_unavailable | 502 |
circuit_breaker | 503 |
Topup Errors
| Error Code | HTTP Status |
|---|---|
topup_not_needed | 400 — Balance is already ≥ 0. No fees to settle. |
Error Recovery
| Scenario | What Happens |
|---|---|
| Payment request expired | Closes, nothing charged, create new |
| Lightning payment failed mid-route | Atomic, funds returned, request stays open |
| Payment confirmed but files not unlocking | Delay in reconciliation, poll get-unlock-status, resolves within seconds |
| API 500 or timeout | Not always safe to retry blindly. Creating request not idempotent. Topup is retry-safe — the server returns the existing pending invoice if one exists; credit is capped at exactly the amount owed. |
| Balance went negative | Expected — service fee deducted post-settlement. Settled payments still deliver. Call POST /api/agent/topup (empty body) before creating new — server mints a bolt11 for exactly -available_sats. |
| Key retrieval failed | One-time, may be marked released. Contact support. |
General rule: Query state rather than retry blindly.
Idempotency
| Operation | Safety | Notes |
|---|---|---|
| Create payment request | Caution | Each call creates new. Retry only if no response. This endpoint does not support idempotency keys. Duplicate submissions create duplicate invoices. |
| Top up | Safe | Empty body. Returns existing pending invoice on retry (reused: true). Credit capped at exact amount owed; overpayments recorded separately. |
| Check balance | Always safe | Read-only |
| Poll unlock status | Always safe | Read-only |
| Get decryption key | One-time | Store on first success. |
| Store file metadata | Caution | May create duplicates |
| Store file key | Safe | Keyed by file ID, overwrites cleanly |
Best Practices
- Client-side deduplication for mutations
- Retry freely for reads
- Persist key immediately
- Query state before retrying 500s
Code Examples
Create Payment Request (curl)
Check Balance (curl)
Create Payment Request (JavaScript)
Settle Outstanding Fees (curl)
API Reference
Complete API reference for all Hypawave Agent API endpoints. For TypeScript/JavaScript, install the official SDK: npm install @hypawave/sdk. For other languages, use the OpenAPI 3.0.3 specification with tools like openapi-generator to auto-generate typed clients.
Base URL
Authentication
All agent endpoints require a Bearer token. Settlement endpoints (get-unlock-status, get-key) support Bearer token or session cookie via dual-auth.
Payment Requests
POST /api/agent/create-invoice
Creates a new payment request. The fiat amount is converted to satoshis at the current BTC price and locked at creation time. Returns a payment URL for settlement. Once the Lightning payment confirms, any attached encrypted data is deterministically unlocked.
State machine: created → settled → unlocked | expired
Required fields
| Field | Type | Description |
|---|---|---|
client_email | string | Payer email |
client_first_name | string | Payer first name |
client_last_name | string | Payer last name |
amount | number | Configurable limits — see GET /api/public-settings |
due_date | string | YYYY-MM-DD format |
Optional fields
| Field | Type | Description |
|---|---|---|
currency | string | Default: USD (40+ supported) |
description | string | Memo or note |
company_name | string | Payer company |
expires_in | string | 1h, 24h, 7d, or null |
payment_destination | string | Override default Lightning address (see note below) |
creator_first_name | string | Your display name |
creator_last_name | string | Your last name |
creator_company_name | string | Your company |
creator_fingerprint | string | Client fingerprint |
Sender fields (creator_*) default to the profile you set during API key creation. Provide them to override for a specific invoice — your saved profile will be updated with the new values.
payment_destination defaults to the API key owner's saved lightning_address. Override per-call for marketplace routing (different seller per invoice), multi-wallet owners, or pass-through flows (agent facilitating for a third-party creator). Funds always flow wallet-to-wallet — Hypawave never takes custody.
Response fields (201)
| Field | Type | Description |
|---|---|---|
ok | boolean | Always true on success |
invoice_id | integer | Unique request ID |
access_token | string | Payment page token |
payment_url | string | Browser-based payment page |
instructions_url | string | Payer agent instructions |
stream_id | uuid | Hypawave stream ID |
amount | number | Amount in currency |
currency | string | Currency code |
sats | integer | Locked sats amount |
btc_usd_rate | number | Locked BTC price |
expires_at | datetime|null | Expiration time |
Error responses
| Code | Error | Description |
|---|---|---|
| 400 | validation_error | Invalid input |
| 401 | invalid_api_key | Bad or missing auth |
| 402 | negative_balance | Outstanding fees block new requests |
| 429 | rate_limit_exceeded | 30/min per identity |
| 502 | price_feed_unavailable | BTC price feed down |
Balance
GET /api/agent/balance
Returns the current balance in satoshis and fiat equivalent. A negative balance means settlement fees are outstanding — this blocks new payment request creation but never blocks delivery or key release.
Query parameters
| Field | Type | Description |
|---|---|---|
currency | string | Optional, default USD |
Response (200)
| Field | Type | Description |
|---|---|---|
available_sats | integer | Balance in sats (can be negative) |
fiat_equivalent | number | Fiat value at current price |
currency | string | Currency code |
btc_price | number | Current BTC price |
has_outstanding_fee | boolean | True if balance is negative |
POST /api/agent/topup
Creates a Lightning invoice that clears outstanding settlement fees and restores the ability to create new payment requests. Fee-settlement only — the server mints a bolt11 for exactly the amount owed; callers cannot specify an amount. Returns 400 topup_not_needed when balance is already at or above zero.
Request body
Empty. Any fields are ignored.
Response (200)
| Field | Type | Description |
|---|---|---|
ok | boolean | Always true on success |
bolt11 | string | BOLT11 Lightning invoice to pay |
payment_hash | string | Payment hash for tracking |
amount_sats | integer | Amount in satoshis |
expires_at | datetime | Invoice expiration |
Key Management
These endpoints require a logged-in browser session (session cookie + CSRF token). They cannot be called with a Bearer token.
POST /api/agent/create-key
Create a new API key. The raw key is returned only once — store it immediately.
Request
| Field | Type | Description |
|---|---|---|
mode | string | "test" or "live" (required) |
label | string | Optional label (max 100 chars) |
Response (201)
| Field | Type | Description |
|---|---|---|
key | string | Full API key (shown once) |
prefix | string | Key prefix for identification |
mode | string | test or live |
Rate limit: 5/hour per IP, 3/hour per identity
POST /api/agent/revoke-key
Revoke an API key. Takes effect immediately — all subsequent requests with this key will be rejected.
| Field | Type | Description |
|---|---|---|
key_id | string | UUID of the key to revoke (required) |
reason | string | Optional reason |
GET /api/agent/list-keys
List all API keys for your identity. Returns prefixes and metadata — never raw keys.
Settlement
POST /api/get-unlock-status
Checks whether payment requests have reached settlement and triggered deterministic unlock. Settlement confirmation is unconditional — once payment confirms, unlock is guaranteed regardless of creator balance or platform state.
Request
| Field | Type | Description |
|---|---|---|
invoice_ids | integer[] | Payment request IDs to check (max 25) |
Response (200)
| Field | Type | Description |
|---|---|---|
unlocked | object | Map of ID to boolean unlock status |
statuses | object | Detailed status per request (unlocked, status, failure_reason, settlement_proof) |
statuses[id].settlement_proof | object|null | Cryptographic proof: payment_hash, preimage (SHA-256 proof of payment), settled_at |
Auth: Bearer token or session cookie. Rate limit: 30/min per IP
GET /api/get-key?invoice_file_id=...
Retrieves the AES-256-GCM encryption key and IV for a settled payment request's attached file. No authentication required — access is gated entirely by settlement proof. Payment is the authorization.
Query parameter
| Field | Type | Description |
|---|---|---|
invoice_file_id | uuid | File UUID (after settlement) |
Response (200)
| Field | Type | Description |
|---|---|---|
encryption_key | string | Base64-encoded AES-256-GCM key |
iv_hex | string | Hex-encoded initialization vector |
Error responses
| Code | Error | Description |
|---|---|---|
| 400 | missing_file_id | No file ID provided |
| 403 | not_paid | Payment not yet settled |
| 403 | key_already_released | Key was already claimed (atomic, one-time) |
| 404 | file_not_found | Invalid file UUID |
| 410 | invoice_expired | Past expiration + grace period |
No auth required. Rate limit: 30/min per IP
OpenAPI Specification
For TypeScript, use the official SDK: npm install @hypawave/sdk. For other languages, the raw OpenAPI 3.0.3 spec is available at /.well-known/openapi.json for use with openapi-generator.