Quick Start

Get a pass into a user's wallet in under 5 minutes.

Step 1 โ€” Get a Token

Exchange your tenant + application credentials for a Bearer JWT (valid 60 minutes).

POST /api/v1/auth/token
{
  "tenant_id":          "your-tenant-id",
  "application_id":     "your-app-id",
  "application_secret": "wp_your_secret",
  "grant_type":         "client_credentials"
}
โ— 200 OK
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type":   "Bearer",
  "expires_in":   3599,
  "scope":        "passes:read passes:write templates:read messages:read messages:write webhooks:write analytics:read"
}
curl -X POST https://api.walletplatform.io/api/v1/auth/token \
  -H "Content-Type: application/json" \
  -d '{
    "tenant_id":          "your-tenant-id",
    "application_id":     "your-app-id",
    "application_secret": "wp_your_secret",
    "grant_type":         "client_credentials"
  }'
using var client = new HttpClient();
var response = await client.PostAsJsonAsync(
    "https://api.walletplatform.io/api/v1/auth/token",
    new
    {
        tenant_id          = "your-tenant-id",
        application_id     = "your-app-id",
        application_secret = "wp_your_secret",
        grant_type         = "client_credentials"
    });

var body = await response.Content.ReadFromJsonAsync<JsonElement>();
var token = body.GetProperty("access_token").GetString();
const response = await fetch(
  'https://api.walletplatform.io/api/v1/auth/token',
  {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      tenant_id:          'your-tenant-id',
      application_id:     'your-app-id',
      application_secret: 'wp_your_secret',
      grant_type:         'client_credentials'
    })
  }
);

const { access_token } = await response.json();
import requests

r = requests.post(
    'https://api.walletplatform.io/api/v1/auth/token',
    json={
        'tenant_id':          'your-tenant-id',
        'application_id':     'your-app-id',
        'application_secret': 'wp_your_secret',
        'grant_type':         'client_credentials'
    }
)

token = r.json()['access_token']
<?php
$payload = json_encode([
    'tenant_id'          => 'your-tenant-id',
    'application_id'     => 'your-app-id',
    'application_secret' => 'wp_your_secret',
    'grant_type'         => 'client_credentials',
]);

$response = file_get_contents(
    'https://api.walletplatform.io/api/v1/auth/token',
    false,
    stream_context_create([
        'http' => [
            'method'  => 'POST',
            'header'  => "Content-Type: application/json\r\n",
            'content' => $payload,
        ],
    ])
);

$token = json_decode($response)->access_token;

Step 2 โ€” Create a Pass

POST to /passes with a template id and your customer data:

POST /api/v1/passes
Headers:
  Authorization:    Bearer eyJhbGci...
  Content-Type:     application/json
  Idempotency-Key:  customer-12345-pass-001

Body:
{
  "template_id":  "3f2a1b4c-8d9e-4c5b-9a3e-7d1f8e4a2c5b",
  "intent":       "loyalty_card",
  "external_ref": "customer-12345",
  "data": {
    "member_name": "Max Mustermann",
    "member_id":   "MBR001",
    "points":      "1500",
    "logo_url":    "https://yourdomain.com/logo.png"
  }
}
โ— 202 Accepted
{
  "id":           "57725a27-2093-42d0-8cb9-d4f1a5e9b3c7",
  "status":       "pending",
  "external_ref": "customer-12345",
  "providers": {
    "google": { "status": "queued" }
  },
  "job_id":       "5b0c61cf-...",
  "created_at":   "2026-05-18T10:00:00Z"
}
curl -X POST https://api.walletplatform.io/api/v1/passes \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: customer-12345-pass-001" \
  -d '{
    "template_id":  "3f2a1b4c-8d9e-4c5b-9a3e-7d1f8e4a2c5b",
    "intent":       "loyalty_card",
    "external_ref": "customer-12345",
    "data": {
      "member_name": "Max Mustermann",
      "member_id":   "MBR001",
      "points":      "1500"
    }
  }'
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", token);
client.DefaultRequestHeaders.Add("Idempotency-Key", "customer-12345-pass-001");

var response = await client.PostAsJsonAsync(
    "https://api.walletplatform.io/api/v1/passes",
    new
    {
        template_id  = "3f2a1b4c-8d9e-4c5b-9a3e-7d1f8e4a2c5b",
        intent       = "loyalty_card",
        external_ref = "customer-12345",
        data = new
        {
            member_name = "Max Mustermann",
            member_id   = "MBR001",
            points      = "1500"
        }
    });

var pass = await response.Content.ReadFromJsonAsync<JsonElement>();
var passId = pass.GetProperty("id").GetString();
const response = await fetch(
  'https://api.walletplatform.io/api/v1/passes',
  {
    method: 'POST',
    headers: {
      'Authorization':   `Bearer ${token}`,
      'Content-Type':    'application/json',
      'Idempotency-Key': 'customer-12345-pass-001'
    },
    body: JSON.stringify({
      template_id:  '3f2a1b4c-8d9e-4c5b-9a3e-7d1f8e4a2c5b',
      intent:       'loyalty_card',
      external_ref: 'customer-12345',
      data: {
        member_name: 'Max Mustermann',
        member_id:   'MBR001',
        points:      '1500'
      }
    })
  }
);

const pass = await response.json();
import requests

headers = {
    'Authorization':   f'Bearer {token}',
    'Idempotency-Key': 'customer-12345-pass-001',
}

r = requests.post(
    'https://api.walletplatform.io/api/v1/passes',
    headers=headers,
    json={
        'template_id':  '3f2a1b4c-8d9e-4c5b-9a3e-7d1f8e4a2c5b',
        'intent':       'loyalty_card',
        'external_ref': 'customer-12345',
        'data': {
            'member_name': 'Max Mustermann',
            'member_id':   'MBR001',
            'points':      '1500',
        },
    },
)

pass_data = r.json()
$payload = json_encode([
    'template_id'  => '3f2a1b4c-8d9e-4c5b-9a3e-7d1f8e4a2c5b',
    'intent'       => 'loyalty_card',
    'external_ref' => 'customer-12345',
    'data' => [
        'member_name' => 'Max Mustermann',
        'member_id'   => 'MBR001',
        'points'      => '1500',
    ],
]);

$response = file_get_contents(
    'https://api.walletplatform.io/api/v1/passes',
    false,
    stream_context_create([
        'http' => [
            'method'  => 'POST',
            'header'  => implode("\r\n", [
                "Authorization: Bearer $token",
                'Content-Type: application/json',
                'Idempotency-Key: customer-12345-pass-001',
            ]),
            'content' => $payload,
        ],
    ])
);

$pass = json_decode($response);

Step 3 โ€” Poll for Status

Pass creation is asynchronous. Poll GET /passes/{id} until status is active (all providers completed) or partial (some completed, others still in-flight).

# Poll until status = active or partial
while true; do
  r=$(curl -s https://api.walletplatform.io/api/v1/passes/$PASS_ID \
       -H "Authorization: Bearer $TOKEN")
  status=$(echo $r | jq -r .status)
  echo "Status: $status"
  [[ "$status" =~ ^(active|partial)$ ]] && break
  sleep 2
done

echo $r | jq .providers.google.save_link
string? googleSaveLink = null;
while (googleSaveLink is null)
{
    await Task.Delay(TimeSpan.FromSeconds(2));
    var r = await client.GetFromJsonAsync<JsonElement>(
        $"https://api.walletplatform.io/api/v1/passes/{passId}");

    var status = r.GetProperty("status").GetString();
    if (status is "active" or "partial")
    {
        googleSaveLink = r.GetProperty("providers")
            .GetProperty("google")
            .GetProperty("save_link").GetString();
    }
}

Console.WriteLine(googleSaveLink); // pay.google.com/gp/v/save/...
async function waitForPass(passId) {
  while (true) {
    const r = await fetch(
      `https://api.walletplatform.io/api/v1/passes/${passId}`,
      { headers: { 'Authorization': `Bearer ${token}` } }
    );
    const pass = await r.json();
    if (['active', 'partial'].includes(pass.status)) return pass.providers;
    await new Promise(rs => setTimeout(rs, 2000));
  }
}

const providers = await waitForPass(passId);
window.location.href = providers.google.save_link;
import time

while True:
    r = requests.get(
        f'https://api.walletplatform.io/api/v1/passes/{pass_id}',
        headers={'Authorization': f'Bearer {token}'},
    )
    data = r.json()
    if data['status'] in ('active', 'partial'):
        save_link = data['providers']['google']['save_link']
        print(f'Google Wallet: {save_link}')
        break
    time.sleep(2)
do {
    sleep(2);
    $r = json_decode(file_get_contents(
        "https://api.walletplatform.io/api/v1/passes/$passId",
        false,
        stream_context_create(['http' => [
            'header' => "Authorization: Bearer $token",
        ]])
    ));
} while (!in_array($r->status, ['active', 'partial']));

$saveLink = $r->providers->google->save_link;
๐ŸŽ‰ That's it! Your pass is now in the user's wallet. For production, use webhooks to get notified instead of polling.