Gyvar docs

Access

What a business needs before it can call this API, and the one thing you still have to ask us for.

Three separate things decide whether a call succeeds: whether the business can hold a key, whether the key authenticates from where you are calling, and - for money only - whether the business is open for spending. They are separate on purpose, so no single mistake and no single stolen credential is enough on its own.

Keys are self-serve

Generate a keypair, upload the public half under your business's API keys, and you have a key id. There is no application, no enablement request and nothing to wait for, in either sandbox or live.

This changed on 2026-09-18. Both surfaces used to be granted per business by us, which made "can I try it" a conversation rather than a signup. If you read older notes saying you need us to switch API keys or sandbox on for you, they are out of date.

We never hold your private key

Which means we cannot reissue it. Rotation is register-a-second-key, then revoke the first. See Signing.

The IP allowlist

A key that can send money authenticates only from the addresses listed against it. It must have at least one, and there is no wildcard. A key with only read and receive, such as a store's key, may have an empty list, which means any address.

ip_not_allowed means the signature was fine and the address was not listed. Egress addresses are easy to get wrong when your code runs behind a NAT or on a platform that rotates outbound IPs, so list every address your traffic can leave from.

What a key may do

Three capabilities, chosen when you register the key and changeable afterwards from the same screen - you do not re-register a key to widen or narrow one.

CapabilityCovers
readEvery GET. On every key, and not removable.
receivePOST /addresses, POST /lightning/invoices, POST /checkout/orders and POST /checkout/orders/{id}/cancel.
moneyEverything that sends money: payouts, transfers and Lightning payments.

Only read is implied. A key registered without asking for anything else can read your balances, transactions and beneficiaries and nothing else - including no minting. Creating an address or an invoice is a write at the provider rather than a read of our own records, so it is granted rather than assumed.

Nothing is granted by leaving it out, either: a registration that does not mention capabilities produces a read-only key, never a broader one.

A call refused for want of a capability answers 403 with details.code of capability_required, naming the one it wanted.

Moving money still needs enabling

The money capability is only half of what the endpoints that send money require: they need two independent grants.

  1. The key must carry the money capability. A key without it cannot spend, whoever holds it.
  2. The business must be opened for money over the API, which is ours to switch on - talk to us.

Either one alone does nothing. A leaked key cannot pay anybody unless the business was also opened, and an opened business arms no key that was not separately granted.

Until both are in place, those endpoints answer 403 with details.code of capability_required (the key) or api_money_not_enabled (the business). Two codes rather than one because the fixes are different: the first is a permission you change on the key you already hold, the second is a conversation.

Once both are in place, those endpoints demand one more thing that the rest of the API does not: an Idempotency-Key header on every call. See Sandbox for where to rehearse it, and Sending money for the exact semantics - the short version is that a retry with the same key replays the first order instead of paying a second time.

Why this one stayed gated

Holding a credential and spending from a balance are different risks, and only the second is irreversible. Opening keys to everyone was worth doing precisely because a key on its own cannot move value - that property is what makes it safe, so it is not one we hand away in the same motion.

Either surface can be closed again

A business can be restricted, and both surfaces can be closed platform-wide, without touching your key. The check runs on every request rather than at registration, so access that is withdrawn stops working on the next call - and access that comes back needs no new key.

Two codes, because the fixes differ:

details.codeWhat happened
api_access_revokedThis business is no longer open for API access at all.
sandbox_unavailableThe key is a sandbox key and sandbox is closed for this business. A live key on the same business is unaffected.

Treat them the way you would treat any other refusal on this API: switch on details.code, and default an unknown code to failure. See Errors.

On this page