Skip to content

API keys and webhooks

The API keys & webhooks page holds the two credentials your systems use.

Your API key

One key per organization. It is the server-to-server credential your backend sends on every API call, and it authenticates as your whole organization.

Danger

An API key can move money. Keep it on your servers. Never put it in a browser bundle, a mobile app, a public repository, or a support ticket.

Rotating

Only the owner can rotate the organization key.

Rotation is atomic: a new key is minted and the old one dies at the same moment.

Warning

The new key is shown once, and there is no way to read it back later.

The old key, including the one your integration is using right now, stops working immediately. There is no overlap window. Have somewhere to put the new key before you click, and expect a gap unless you can deploy it instantly.

Rotate when someone with access leaves, when a key may have been exposed, or on whatever schedule your security policy sets.

Personal keys

If you signed in as a person, you can mint and rotate a key scoped to you, carrying your own role. Useful when you want per-person attribution and per-person revocation rather than one shared organization key.

The organization root key and personal keys are rotated separately, from different places.

Webhooks

Rather than having your systems poll for payment status, register one endpoint and JET pushes every state change to you.

Managing webhooks needs the admin role or higher.

Registering

Enter the HTTPS URL your systems listen on and register it.

You get back a signing secret, shown once.

Danger

Store the signing secret immediately. It is never displayed again, and there is no way to read it back: a read path would turn a read-only credential leak into the ability to forge deliveries to your own system.

One endpoint at a time

Your organization has exactly one webhook endpoint. Registering a new URL replaces the previous one and mints a fresh secret: the old secret stops working straight away.

URL rules

Rule Why
Must be https Deliveries carry transaction data and a signature. Over plain HTTP an observer sees both
No private or internal addresses localhost, 127.*, 10.*, 192.168.*, 169.254.*, .internal, .local are refused

The second rule exists because a webhook target is chosen by the caller. Without it, a URL could be used to make JET issue requests inside its own network, on a schedule, with retries.

What gets delivered

A signed POST on every payment transition, and when a deposit, batch or bank withdrawal finishes:

Event Fires when
transaction.quoted A price is locked
transaction.funded Funds have left your wallet
transaction.paid_out The recipient has been paid
transaction.reconciled Everything agrees: the payment is done
transaction.refunded The payment was cancelled and the money returned
transaction.in_doubt The outcome is ambiguous and parked
batch.rejected A batch was refused before anything moved
batch.completed No item of a batch is still running
onramp.delivered A deposit reached your wallet
onramp.refunded A deposit was returned to the payer
offramp.paid A bank withdrawal reached the beneficiary

Deliveries are at-least-once, retried with backoff, and dead-lettered rather than dropped if your endpoint stays unreachable. Each delivery carries a stable delivery ID, so a retry can be recognised and ignored.

Your engineers should verify the signature on every delivery before acting on it. Verifying signatures covers the exact scheme with working code.

Checking what is registered

The page shows the URL currently registered, or that none is. It never shows the secret.

Turning it off

Deleting the endpoint stops delivery and destroys the signing secret. Deliveries already queued are not cancelled: they fail and dead-letter rather than disappearing, so nothing is silently lost.

Deleting is confirmed behind a dialog, because it destroys a secret that cannot be recovered.

Rotating a signing secret

Register the same URL again. A fresh secret comes back and the old one dies immediately.

There is no overlap window, so if you cannot tolerate rejected deliveries, deploy a receiver that accepts either secret first, rotate, then drop the old one.