Skip to main content
This is the full path for one test client, in the order the API expects it:
Every step produces an id that the next step needs. Don’t skip ahead — the two most common integration failures are an organization without billing_id and card holders created before the webhook exists. Both are avoided by simply following the order below. Grab coffee. ☕ Let’s go.

Step 0: Register (sandbox)

👉 sandbox-api.opencard.io/register You get an Account + admin user. Verify email. Log in. Your accountId is in the dashboard URL or API responses.

Step 1: Create an account_client and get a token

Save the access_token. All subsequent calls:
Scopes are space-separated. Request only what you need. Full list in Authentication. Always send Accept: application/json so error responses stay JSON (not an HTML login page).
Verify: GET /api/v1/application/payment-products returns 200. Auth works.

Step 2: Enable a payment product (once per account)

Save payment_product_id. You need it for the TPA in step 4. → Payment product setup

Step 3: Create a billing profile 🧾

The billing profile is the client’s invoice profile and the switch that turns on products. The product_* flags decide which webhook events the client is allowed to subscribe to — so this must exist before the organization and the webhook.
Response → save id as billing_id.
product_transaction: true is what allows card_transaction_* events on the webhook later. Creating a webhook with transaction events for an organization whose billing lacks this flag (or that has no billing_id at all) fails.
→ Model: Billing

Step 4: Create the TPA 📜

TPA = Transaction Processing Authorisation. Legal permission for the client’s transaction data to flow. First, check who may sign for the company (optional, but saves a round-trip with the client):
Response includes signature_combinations — the people you’ll add as signatories in step 5. Then create the TPA:
Org number formats: Response → save id as tpa_id. → TPA flow

Step 5: Add signatories → email goes out 📧

The email is queued immediately with a signing link. Repeat for each signatory required by signature_combinations.
Signatories can only be updated/deleted while signed=false. Once signed, they’re locked.
Don’t wait for the signature here — continue with steps 6 and 7 right away so the webhook is in place when tpa.signed fires.

Step 6: Create the organization 🏢

The organization is the runtime container for the client. It links the TPA (legal) and the billing (products) together.
reference_id = your internal client ID. It comes back in every webhook. Response → save id as organization_id. → Model: Organization

Step 7: Create the webhook 🔔

Challenge happens immediately. OpenCard sends:
Your endpoint must respond with header:
Verify: GET .../organizations/$ORG_ID/webhooks shows active: true. Until then no events are delivered.
The webhook is not optional. Card holder lifecycle and PDPC signing write events to it — an organization without a webhook cannot complete PDPC signing. Create it now, before any card holder.
→ Webhook setup

Step 8: TPA gets signed → your first webhook ✍️

The signatory clicks the link from step 5, reads the TPA and signs with eID. When every required signatory has signed:
  • Signed PDF is generated and stored
  • tpa.signed is POSTed to your webhook — this is your first real event
  • TPA status → pending-activation, then activated once confirmed
Verify: you received X-Event: tpa.signed with organization.reference_id = client_acme_001. → eID signing · Event reference

Step 9: Create card holders 👤

Two paths — pick one. Full guide → Card holder onboarding.

Path A: Email + eID (new employee)

John gets an email → signs the PDPC with eID → card_holder.identified → transactions flow.
language is optional. If omitted, OpenCard picks the PDPC language from the TPA country and falls back to English where no translation exists.

Path B: identity_id (instant — person already in OpenCard)

card_holder.identified fires instantly + retroactive transaction webhooks replay. ⚡ Verify: you received X-Event: card_holder.identified.

Step 10: Receive your first transaction 🎉

Once the issuer delivers transaction states for an identified card holder:
Nothing arriving yet? Fire a test event: POST .../webhooks/{webhookId}/test/card.transaction.authorized. You did it. From zero to live transaction data.

Recap — what you stored

Repeat steps 3–9 for every new client. Steps 0–2 are once per account.

What’s next?