Create a Pass from a Klaviyo Flow Using a Webhook Action
Updated June 3, 2026
TL;DR: Use Klaviyo's native Webhook flow action to call the PassNinja API and issue a pass — no code required.
- Add a Webhook action to any Klaviyo flow
- POST to
https://api.passninja.com/v1/passeswith your template ID and pass fields - Map pass fields using Klaviyo liquid tags — no JavaScript needed
- PassNinja automatically writes the serial number back to the Klaviyo profile
Overview
Klaviyo's native Webhook flow action sends an HTTP POST directly to the PassNinja API. You configure the URL, headers, and request body in the Klaviyo UI — no code required. This is the fastest way to issue a pass from a Klaviyo flow when you don't need conditional logic.
Prerequisites
| Requirement | Details |
|---|---|
| PassNinja account | With at least one pass template created |
| Klaviyo account | Manager, Admin, or Owner access |
| Klaviyo integration connected | PassNinja → Integrations → Klaviyo must be connected |
You will need three values from PassNinja:
| Value | Where to find it |
|---|---|
PASSNINJA_API_KEY | PassNinja → Settings → API Keys |
PASSNINJA_ACCOUNT_ID | PassNinja → Settings → API Keys (format: aid_0x...) |
PASSNINJA_TEMPLATE_ID | PassNinja → Pass Templates → select template (format: ptk_0x...) |
Step 1 — Add a Webhook action to your flow
In Klaviyo's flow builder, click the + button at the point where you want the pass to be created, then choose Webhook.
Good trigger points:
- Subscribed to List — issue a welcome pass when someone joins
- Placed Order — issue a post-purchase loyalty pass
- Custom metric — issue a pass on loyalty enrollment or any business event
Step 2 — Configure the request
| Field | Value |
|---|---|
| Method | POST |
| URL | https://api.passninja.com/v1/passes |
Step 3 — Add headers
| Header | Value |
|---|---|
X-API-KEY | Your PassNinja API key |
X-ACCOUNT-ID | Your account ID (e.g. aid_0x1a2b3c) |
Content-Type | application/json |
Step 4 — Set the request body
{
"passTemplate": "ptk_0x4d5e6f",
"pass": {
"member-name": "{{ person.first_name }} {{ person.last_name }}",
"member-email": "{{ person.email }}",
"phone-number": "{{ person.phone_number|default:'' }}"
},
"recipient": {
"email": "{{ person.email }}",
"name": "{{ person.first_name|default:'' }}"
}
}
Replace ptk_0x4d5e6f with your actual template ID.
Replace the keys inside pass with the api_field_name values from your pass template — find these in PassNinja → Pass Templates → select your template → Fields.
Referencing custom Klaviyo profile properties
Use {{ person.properties.your_property_name|default:'' }} to map any custom profile property to a pass field:
{
"passTemplate": "ptk_0x4d5e6f",
"pass": {
"member-name": "{{ person.first_name }} {{ person.last_name }}",
"member-email": "{{ person.email }}",
"loyalty-tier": "{{ person.properties.loyalty_tier|default:'Standard' }}",
"points-balance": "{{ person.properties.loyalty_points|default:0 }}"
},
"recipient": {
"email": "{{ person.email }}",
"name": "{{ person.first_name|default:'' }}"
}
}
Step 5 — Save and activate
Save the Webhook action and activate your flow. Klaviyo will send the request to PassNinja each time a profile reaches that step.
How the profile write-back works
After PassNinja creates the pass, it automatically fires a Pass Created event back to Klaviyo. The customer profile is created (or updated) with:
| Profile Field | Value |
|---|---|
external_id | The pass serial number — used in email/SMS pass links |
email | Customer email (if included on the pass) |
phone_number | Customer phone (if included on the pass) |
PassNinja also writes a WalletPass Application Object record in Klaviyo's Custom Objects, linked to the profile via external_id. This record tracks pass state (active, uninstalled, deleted), the download URL, platform, and timestamps.
To link directly to the customer's pass in any subsequent email or SMS, use:
https://passninja.com/p/{{ person.external_id }}
Troubleshooting
Webhook not firing or returning an error
Check the webhook delivery log: Klaviyo → Flows → select your flow → Activity. Look for non-2xx responses and read the response body — PassNinja returns a JSON error message describing the problem.
Common causes:
- Wrong API key or account ID in the headers
- Pass field keys don't match the
api_field_namevalues in your template — check PassNinja → Pass Templates → Fields - A required field is missing or empty
external_id not set on the profile
- Confirm the Klaviyo integration is connected in PassNinja → Integrations → Klaviyo
- Allow a few seconds — the write-back fires asynchronously after pass creation
- Search for the profile in Klaviyo using the pass serial number
Support
- Email: support@passninja.com
- API Reference: passninja.com/documentation
- All Klaviyo tutorials: passninja.com/tutorials/klaviyo