Getting Started
Use REST against your SnapWallet API host. Server-side integrations should use organization API keys (see below). Use Dashboard → API keys to create keys and choose what each key may access (or leave full access). For every HTTP route and schema, open the tab (loaded from OpenAPI).
1. Configure base URL
# Base URL (no global /api prefix in default Nest bootstrap)
export API=https://your-api-host2. Integration fetch helper (API key)
const API = process.env.SNAPWALLET_API_BASE_URL;
const SNAPWALLET_API_KEY = process.env.SNAPWALLET_API_KEY;
async function api(path, { method = 'GET', body } = {}) {
const headers = {
Accept: 'application/json',
'api-key': SNAPWALLET_API_KEY,
};
if (body) headers['Content-Type'] = 'application/json';
const res = await fetch(`${API}${path}`, { method, headers, body: body ? JSON.stringify(body) : undefined });
if (!res.ok) throw new Error(await res.text());
return res.status === 204 ? null : res.json();
}3. Public pass creation
// Public issuance — POST /v1/snap (no API key; legacy /snap unchanged)
const res = await fetch(`${API}/v1/snap`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
body: JSON.stringify({
fullName: 'Jane Doe',
phoneNumber: '27123456789',
cardNumber: '6006123456789012',
email: 'jane@example.com',
passId: 'PASS_TEMPLATE_UUID',
type: 'apple',
}),
});
if (!res.ok) throw new Error(await res.text());/api prefix unless you add one in bootstrap.http://localhost:4000Authentication and entitlements
Integrations: send your organization API key on protected /v1/* integration routes using api-key: <secret> (also accepted: x-api-key). Keys are not accepted on internal console routes (e.g. /giftcard without the /v1 prefix) — use the versioned public paths from OpenAPI instead. Do not embed keys in browsers or mobile apps.
Open issuance: POST /v1/snap and public enrollment under /v1/snap/enrollment/public do not require an API key. Send only one auth method per request — do not combine Authorization: Bearer with api-key.
Console: the dashboard signs in with POST /auth/login and uses Authorization: Bearer <jwt>. JWTs are short-lived sessions, not a substitute for API keys on servers.
What a key may do: in the dashboard you pick capabilities in plain language (gift cards, loyalty, webhooks, and so on). That becomes a small permissions map on the server. Leave full access on unless you intentionally want a narrower integration. The server always intersects what you allow with your subscription package. Workspace and organization settings (users, roles, forms, boards, workspaces, org settings, pass templates) are not assignable to API keys — use a dashboard JWT session for those.
Organization binding on /v1: every authenticated /v1/* route (except open /v1/snapissuance) is scoped to the caller's organization. API keys and normal JWT sessions can only read or mutate resources in their own org. A path or body organizationId that does not match returns 403. Accessing another org's resource by UUID returns 404 (not 403) so existence is not leaked. Super-admin JWT sessions bypass org scoping and may pass any organization id in list routes.
// Browser / short-lived human session only — use API keys for servers
async function apiBearer(path, { method = 'GET', token, body } = {}) {
const headers = { Accept: 'application/json', Authorization: `Bearer ${token}` };
if (body) headers['Content-Type'] = 'application/json';
const res = await fetch(`${API}${path}`, { method, headers, body: body ? JSON.stringify(body) : undefined });
if (!res.ok) throw new Error(await res.text());
return res.status === 204 ? null : res.json();
}Keys carry the same authorization surface as scoped features on your account. Store them in a secret manager, rotate on compromise, and never commit them to source control.
HTTP and errors
SnapWallet uses JSON bodies for REST. Send Content-Type: application/json on writes. Errors from Nest HttpException usually include statusCode, message, and error.
Response body
{
"statusCode": 401,
"message": "Incorrect username and password",
"error": "Unauthorized"
}Response body
{
"statusCode": 403,
"message": "Not Authorized. Contact your admin.",
"error": "Forbidden"
}Solutions
Solution mix is driven by your package and key scopes (see feature keys on each card). The published OpenAPI document lists versioned integration routes under /v1 (e.g. GET /v1/membership-program/organization/:id for membership programs).
Route prefixes: giftcardgiftcard-templategiftcard-transaction
Feature keys: gct (templates), gtx (transactions)
Route prefixes: loyalty-programloyalty-client
Feature keys: lyp (loyalty-client and loyalty-program routes), lyc (customers elsewhere)
Route prefixes: pass-templatemembership-programmembership-enrolment
Feature keys: msp (program) and/or ptm (pass templates)
Route prefixes: eventsevents-customer
Feature keys: evn, eal
Workflow examples
Distribution and enrolment combine templates, programs, and public issuance; see API Reference for all /v1 routes.
List membership programs (integration)
GET /v1/membership-program/organization/:id returns program metadata for enrolment flows. Pass template listing (GET /v1/pass-template/organization/:id) requires a dashboard JWT session, not an API key.
// Server integration — list membership programs (versioned public API)
await api('/v1/membership-program/organization/ORG_UUID');List gift cards (integration)
// Example: list gift cards for an organization (versioned public API)
await api('/v1/giftcard/organization/ORG_UUID');Webhooks
Register outbound webhooks with POST /v1/trigger-events (same payload as the legacy route). Your delivery URL must be HTTPS. Managing triggers requires the etr feature. Configure from Dashboard → Webhooks or the REST routes in API Reference.
Each delivery is a JSON body { event, organizationId, ...payload }. The event string matches the trigger you selected; extra fields depend on that event (for example pass serial numbers on snap captured, or ticket id on event ticket issued). When action is post_webhook, configure an optional signing secret in data to verify x-snapwallet-signature (HMAC-SHA256 of the raw JSON body).
Available trigger events (by solution area)
- Gift cards: gift card issued (
pubsub_public_card_created_event), gift card transaction (pubsub_gift_card_transaction_event) - Loyalty: customer created (
pubsub_customer_created_event), points collected (pubsub_points_collected_event), reward goal reached (pubsub_snap_goal_reached_event), snap captured (pubsub_snap_captured_event) - Membership: enrolment created (
pubsub_membership_enrolment_created_event) - Access (events): event ticket issued (
pubsub_event_ticket_issued_event)
Register with API key
await api('/v1/trigger-events', {
method: 'POST',
body: {
title: 'Notify CRM',
description: 'Forward loyalty snaps',
trigger: 'pubsub_snap_captured_event',
delivery: 'https://example.com/webhooks/snapwallet',
action: 'post_webhook',
organizationId: 'ORG_UUID',
isActive: true,
data: {},
},
});Consumer handler sketch
// Your HTTPS endpoint receives delivery payloads from SnapWallet (shape depends on trigger).
// Verify authenticity using your shared secret or signing scheme once documented for your tenant.
app.post('/webhooks/snapwallet', express.json(), (req, res) => {
console.log('Trigger payload', req.body);
res.status(200).send('OK');
});