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 "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 -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 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
$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"];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.
{
"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.