WalletPassAPI Docs

Guides

Paging

Go through every pass with a cursor, or jump to a numbered page.

List passes answers a page at a time, newest first: 50 passes unless you ask for another limit, up to 100. There are two ways through the rest.

With a cursor

The answer's nextCursor asks for the page after it. Send it back as cursor, with the same search and filters, until it's null:

curl "https://api.walletpassapi.com/v1/passes?status=active&limit=100&cursor=MTc5MTQ4NzkzNTgwMy5wYXNzXzRmMmE5" \
  -H "Authorization: Bearer $WALLET_API_KEY"
let cursor = null;
do {
  const query = new URLSearchParams({ status: "active", limit: "100", ...(cursor ? { cursor } : {}) });
  const res = await fetch(`https://api.walletpassapi.com/v1/passes?${query}`, {
    headers: { Authorization: `Bearer ${process.env.WALLET_API_KEY}` },
  });
  const page = await res.json();
  for (const pass of page.passes) console.log(pass.serialNumber);
  cursor = page.nextCursor;
} while (cursor);
import os

import requests

cursor = None
while True:
    params = {"status": "active", "limit": 100, **({"cursor": cursor} if cursor else {})}
    page = requests.get(
        "https://api.walletpassapi.com/v1/passes",
        headers={"Authorization": f"Bearer {os.environ['WALLET_API_KEY']}"},
        params=params,
    ).json()
    for p in page["passes"]:
        print(p["serialNumber"])
    cursor = page["nextCursor"]
    if not cursor:
        break
<?php

$cursor = null;
do {
    // http_build_query leaves out a null cursor.
    $query = http_build_query(["status" => "active", "limit" => 100, "cursor" => $cursor]);
    $ch = curl_init("https://api.walletpassapi.com/v1/passes?" . $query);
    curl_setopt_array($ch, [
        CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("WALLET_API_KEY")],
        CURLOPT_RETURNTRANSFER => true,
    ]);
    $page = json_decode(curl_exec($ch), true);
    foreach ($page["passes"] as $pass) {
        echo $pass["serialNumber"], "\n";
    }
    $cursor = $page["nextCursor"];
} while ($cursor);

A cursor holds its place, not a count: passes made while you page don't push others onto the next page, so you never see one twice or miss one that was there when you started. Use it to go through everything, such as to sync your own records.

Send a cursor with the search it came from. One that isn't from this endpoint is refused with invalid_cursor.

With page numbers

To show a list with numbered pages, send page (1 to 10,000) instead of cursor. The answer adds total, every pass the search matches, and page:

{ "passes": [], "nextCursor": null, "total": 3214, "page": 2 }

Numbered pages are counted afresh each time, so a pass made between two requests moves the rest along by one. That's right for a screen a person looks at; to go through everything, use the cursor. Send page or cursor, not both.

Everything at once

For a spreadsheet of every pass a search finds, export them as CSV: up to 100,000 in one file.