Quickstart: issue your first wallet pass

Issue an Apple Wallet and Google Wallet pass with the Shakewell Wallet API in four steps, with cURL, Node, PHP and Python examples you can paste.

Last updated 2026-11-05

You need an account on a plan with API access, one published template and an API key. This takes about five minutes.

1. Check your key and find a template ID

cURL
curl "https://api.shakewellwallet.com/api/public/v1/card-templates?per_page=5" \
  -H "Authorization: Bearer $SHAKEWELL_API_KEY" \
  -H "Accept: application/json"

A 200 response confirms the key works. Each item in data.data has a numeric id. Use it as template_id below.

2. Create a pass

person is required. Which person fields are mandatory depends on the template, because the template's signup fields become validation rules. A missing one returns 422 listing the field.

cURL
curl -X POST https://api.shakewellwallet.com/api/public/v1/wallet-passes \
  -H "Authorization: Bearer $SHAKEWELL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
  "template_id": 38,
  "person": {
    "forename": "Ada",
    "surname": "Lovelace",
    "emailAddress": "ada@example.com"
  }
}'
Node.js
// Node 18+ (built-in fetch)
const res = await fetch("https://api.shakewellwallet.com/api/public/v1/wallet-passes", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SHAKEWELL_API_KEY}`,
    "Content-Type": "application/json",
    Accept: "application/json",
  },
  body: JSON.stringify({
    template_id: 38,
    person: { forename: "Ada", surname: "Lovelace", emailAddress: "ada@example.com" },
  }),
});
const body = await res.json();
if (!res.ok) throw new Error(`${res.status} ${body.error_code ?? body.error}: ${body.message}`);
console.log(body.data.pass_id, body.data.install_urls.universal);
PHP
<?php
$ch = curl_init("https://api.shakewellwallet.com/api/public/v1/wallet-passes");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("SHAKEWELL_API_KEY"),
        "Content-Type: application/json",
        "Accept: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "template_id" => 38,
        "person" => ["forename" => "Ada", "surname" => "Lovelace", "emailAddress" => "ada@example.com"],
    ]),
]);
$body = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($status >= 400) {
    throw new RuntimeException("$status " . ($body["error_code"] ?? $body["error"]) . ": " . $body["message"]);
}
echo $body["data"]["pass_id"], " ", $body["data"]["install_urls"]["universal"];
Python
import os
import requests

res = requests.post(
    "https://api.shakewellwallet.com/api/public/v1/wallet-passes",
    headers={
        "Authorization": f"Bearer {os.environ['SHAKEWELL_API_KEY']}",
        "Accept": "application/json",
    },
    json={
        "template_id": 38,
        "person": {"forename": "Ada", "surname": "Lovelace", "emailAddress": "ada@example.com"},
    },
    timeout=30,
)
body = res.json()
if not res.ok:
    raise RuntimeError(f"{res.status_code} {body.get('error_code') or body.get('error')}: {body['message']}")
print(body["data"]["pass_id"], body["data"]["install_urls"]["universal"])

3. Read the response

A 201 response returns the pass. pass_id is the identifier to use in later calls, and install_urls.universal is the link to give the customer.

201 Created (abridged)
{
  "message": "Wallet pass created successfully",
  "data": {
    "id": 248,
    "pass_id": "72Fs3a9OH1Qqrmapw7aGC9",
    "template_id": 38,
    "status": "active",
    "install_urls": { "universal": "https://..." }
  }
}

4. Deliver the pass

Send install_urls.universal by email, SMS or QR code. Opened on an iPhone it offers Apple Wallet, and on Android it offers Google Wallet. Until the customer adds it, is_installed is false and push notifications to it return PASS_NOT_INSTALLED.

Next: update the pass, send a push notification, or read the full OpenAPI reference.