Skip to main content
A card holder = one person in one organization whose card transactions you want in your EMS. There are two ways to create them. This is one of the most important decisions in your integration — pick based on whether the person already exists in OpenCard or not.
Card holders come after client setup (billing, TPA, organization, webhook). See the full onboarding flow if you have not finished Phase 1 yet.

At a glance


Path 🅰️ — Email + eID (self-service)

Use when the person doesn’t exist in OpenCard yet — typical for new employees joining a client.

Create

What happens

  1. Card holder + PDPC record created
  2. 📧 Email queued — subject: We need your approval.
  3. Link: https://{env}/accounts/{accountId}/pdpcs/{pdpcId}/sign/{token}
  4. User reads PDPC → checks consent → identifies with eID
  5. On eID success → identity linked → card_holder.identified webhook
  6. Retroactive transactions dispatched (everything since last card invoice)
  7. New transactions flow in real time

Timeline

Subscribe to card_holder.identified — that’s your signal that transactions are coming (including a retroactive batch). Don’t wait for card_holder.signed.pdpc alone; identification is what unlocks the pipe.
Full eID details → eID Signing

Path 🅱️ — identity_id (instant)

Use when the person already exists in OpenCard on this TPA — e.g. they have corporate cards from the issuer, or were onboarded to another organization under the same TPA. An identity = a physical person (SSN-linked via eID). They may already have cards attached. You skip the email entirely and link directly.

Step 1: List identities on the TPA

Filter to people not yet in your org:
Response (per identity):

Step 2: Create card holder with identity_id

What happens

  1. Card holder created
  2. Immediately linked to existing identity → identify() called
  3. 🔔 card_holder.identified webhook fires right away
  4. 🚀 SendRetroactiveWebhookEventsJob dispatched — all historical transaction states for their cards on this TPA are replayed to your webhook
  5. New transactions flow in real time from this point

Timeline

The retroactive burst can be large — all transaction states since last invoice replay as webhooks. Make sure your handler can upsert by transaction id and handle the volume.

Validation rules

  • identity_id must exist
  • Identity must belong to a client linked to this TPA — you can’t use identities from a different client’s TPA
  • Either email or identity_id required (not both required, but one must be present)
  • reference_id must be unique within the organization (create and update)

Which path should I use?


Client already receives transactions from the issuer another way? See Current card issuer integration.

Webhooks to handle

Your integration should key off card_holder.identified as the moment transactions are expected.

Update / delete

Update

reference_id is required. email is optional — omit it to keep the current value (including null for identity-linked holders without email). Change reference ID only (no PDPC email if already identified / no email on record):
Change reference ID and email (may resend PDPC email — see below):
PDPC email is resent only when all of: PDPC unsigned or no identity_id, skip_pdpc_email is false, and the card holder has an email address. reference_id must be unique within the organization. Duplicate → 400 Bad Request with message Card holder reference … already exists (same as create).

List card holders

Supports the same filters as before (q, reference_id, where_ssn_set, where_signed_pdpc, where_email_delivered). Response (per item):
You no longer need a separate GET .../tpas/{tpaId}/identities call just to show names in a card holder list — read identity from this endpoint. Keep the identities endpoint for Path 🅱️ onboarding (finding identity_id to create with).

meta in API responses

Check consent status without polling webhooks: