Skip to main content
The TPA is the legal side of a client. This guide is the operational side: the three objects that make a client actually work in OpenCard.
Do this per client, right after you have created the TPA and added signatories. You do not need to wait for the TPA to be signed — in fact you want the webhook in place before it is signed so tpa.signed lands in your app.
Where this fits: Customer onboarding steps 1, 5 and 6. The TPA itself is covered in TPA flow.

What each object does

None of them is optional. See Common mistakes for what breaks without each.

1. Create the billing profile

Response → save id as billing_id.
One billing profile can be shared by several organizations. Every organization with the same billing_id becomes one line on your OpenCard invoice. Use that when a client has multiple legal entities or departments but one finance function. → Model: Billing
API reference → Create billing profile

2. Create the organization

Response → save id as organization_id.

Already created an organization without billing_id?

Fix it with a PUT — no need to delete and recreate:

One client, several organizations?

Usually one client = one organization. Split only when the client needs separate webhook endpoints, separate event subscriptions, or separate card-holder groups. All of them can point at the same tpa_id and billing_id. API reference → Create organization · Model: Organization

3. Create the webhook

Response includes secretsave it, you need it to answer the challenge. OpenCard immediately sends GET {url}?challenge=… with X-Event: challenge. Your endpoint answers with X-Verify-Token: HMAC-SHA256(challenge, secret). When that passes, the webhook is active and events start flowing. Verify:
active: true. If it is false, the challenge failed — see Webhook setup for the handshake in detail, authentication headers and the test endpoint.
Event flags are validated against the billing. Requesting card_transaction_* when the organization’s billing has product_transaction: false — or when the organization has no billing_id — is rejected. Fix the billing (or the billing_id) first, then create the webhook.
API reference → Create webhook · Full guide → Webhook setup · Event reference

Done — what you should have

And on the OpenCard side:
  • GET .../organizations/{organizationId} shows tpa_id and billing_id set
  • GET .../organizations/{organizationId}/webhooks shows one webhook with active: true
Now you can add employees → Card holder onboarding. When the TPA is signed you will see it arrive as tpa.signed on the webhook you just created.

Common mistakes


Using the ocTPA plugin?

The plugin hands you billing, tpa and tpa_signatories in onDataSend. It does not create the organization or the webhook. Do steps 2 and 3 in your onDataSend handler right after the billing and TPA calls. → Plugins