UlasendUlasendDocs

Authentication

Use mode-isolated, least-privilege Bearer keys for Merchant API requests.

Merchant API routes live under /api/v1. Send the raw API key in the Authorization header on every request:

Authorization: Bearer pk_test_...   # or pk_live_...

Never put a secret key in checkout JavaScript, a mobile application, a URL, analytics, or source control. Call Ulasend from your server and keep each key in a secret manager.

Test and live mode isolation

Key prefixModeBehavior
pk_test_TestMock receive addresses and simulated payments; never touches real money.
pk_live_LiveReal receive addresses and blockchain payments.

The credential's mode always wins. A pk_test_ key cannot create, list, or mutate live objects by sending livemode: true. A live key cannot read test objects by changing a query parameter. Test and live idempotency keys also occupy separate namespaces.

Scopes

Every key has explicit scopes. A :write scope also satisfies the matching :read permission. Create separate keys for separate services, and grant only what that service needs.

ResourceScopesIncluded by default?
Invoicesinvoices:read, invoices:writeYes
Payment linkspayment_links:read, payment_links:writeYes
Productsproducts:read, products:writeYes
Transactionstransactions:readYes
Balancebalance:readYes
Payoutspayouts:read, payouts:writeRead only
Payout walletspayout_wallets:readRead only
Settingssettings:read, settings:writeRead only
Webhookswebhooks:read, webhooks:writeNo—grant explicitly

A missing permission returns 403 and names the required scope. Money movement and security configuration should use dedicated keys, not the broad key used by a storefront. Bearer-key webhook write access is limited to test endpoints; live webhook changes are dashboard-only.

Key management

Create, list, and revoke keys from an authenticated Dashboard session. These operations are restricted to organization owners/admins; an API key cannot create a successor key or revoke recovery access. Browser mutations require same-origin requests, and creating a live key requires an AAL2/MFA session.

The raw key is returned once. Ulasend stores only its prefix and SHA-256 hash. If a key is exposed, revoke it, create a replacement with the minimum scopes, deploy the replacement, and review its last-used timestamp and audit trail.

Idempotency for create requests

Send a unique Idempotency-Key on retryable create requests:

Idempotency-Key: wc-order-10482-create-v1

Keys must contain 8–255 printable characters. Ulasend binds the key to the merchant, mode, operation, and canonical request body for 24 hours.

  • An identical retry returns the stored response with Idempotency-Replayed: true.
  • Reusing a key with a different request body returns 409.
  • If the original request is still running, the duplicate returns 409 idempotency_in_progress and Retry-After: 1.

Generate the key from your own immutable operation id, not from the amount alone. A good pattern is <platform>-<order-id>-<operation>-v1. Retrying an ambiguous timeout with the same key is safe; changing the order should use a new operation version.

Typical storefront key

A custom site, Shopify adapter, or WooCommerce adapter that creates one invoice per order normally needs only:

invoices:write
transactions:read

Add webhooks:write only to a separate test setup key when automating test endpoint configuration. Live endpoint setup and secret rotation stay in the owner/admin Dashboard flow.