API keys
IT / TechnicalAPI keys let an external system authenticate against Preb's public API. A key belongs to one workspace and acts on behalf of that workspace. Today, keys are used to record revenue through the transactions endpoint.
Creating a key
Only workspace admins and owners can create or manage keys.
Open API keys
In your workspace, go to Integrations → API keys
(/w/{workspace}/integrations/api-keys).
Create a key
Click Create key and give it a name (1–120 characters). Names must be
unique among your active keys, so pick something that identifies where it
will be used — e.g. Zapier production.
Copy the secret
Preb shows the secret once. Copy it and store it in your secrets manager before closing the dialog (see below).
The one-time secret
A key has two parts:
- A prefix like
pk_a1B2c3D4— a public identifier (pk_followed by 8 characters). This is the only part Preb shows you again later. - A secret — a 40-character random string shown exactly once, at creation time.
prefix: pk_a1B2c3D4
secret: V1StGXR8_Z5jdHi6B-myT_pkb5tF2rN0c8Qm9aRk
The secret is shown only once
Preb stores the secret encrypted (it is never displayed again and never appears in any list or log). If you lose it, you can't recover it — revoke the key and create a new one. To stop you from closing the create dialog too early, it asks you to copy the secret and re-type the prefix before it lets you out.
Authentication
Preb does not use a plain bearer token. Instead, each request is signed: you compute an HMAC of the exact request body using your secret as the key, and send the prefix plus that signature.
The Authorization header format is:
Authorization: Bearer <prefix>:<hex(HMAC-SHA256(secret, rawBody))>
A worked example in Node.js:
import crypto from "node:crypto";
const prefix = "pk_a1B2c3D4";
const secret = "V1StGXR8_Z5jdHi6B-myT_pkb5tF2rN0c8Qm9aRk";
// Sign the EXACT bytes you send as the body.
const body = JSON.stringify({
email: "buyer@example.com",
amount: 4900,
currency: "EUR",
transaction_at: "2026-06-29T10:00:00Z",
});
const signature = crypto
.createHmac("sha256", secret)
.update(body, "utf8")
.digest("hex");
await fetch("https://app.preb.co/api/public/transactions", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${prefix}:${signature}`,
},
body,
});
Sign the raw body, byte-for-byte
The signature must cover the exact bytes you transmit. If a framework
re-serialises your JSON (reordering keys or changing spacing) after you sign it,
the signature won't match and you'll get 401 unauthorized. Build the body
string once, sign that string, and send that string.
Every authentication failure — a missing or malformed header, an unknown or
revoked prefix, or a wrong signature — returns the same opaque 401 unauthorized.
There's no way to tell which part failed, by design.
Revoking a key
In Integrations → API keys, click Revoke next to a key. Revocation takes effect immediately and is idempotent — once revoked, the key can never authenticate again, and revoking it twice is harmless. Revoked keys drop off the list (only active keys are shown). If a key may be compromised, revoke it and issue a new one.
Audit log
Creating and revoking keys is recorded in your workspace audit trail as
credential.api_key.created and credential.api_key.revoked. The entries
capture the key's name and prefix and who made the change — never the secret,
which is never written to any log.