PassHive

PassHive API

Issue Apple Wallet and Google Wallet loyalty cards from your own POS, app or website. Base URL: https://passhive.app/v1. Requests and responses are JSON.

Authentication

Create a key in the dashboard (API keys). Send it as a bearer token. Keys are shown once; keep them on your server, never in a browser or app.

Authorization: Bearer ph_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

GET/v1/me

Returns your business, card design and plan.

Customers and cards

Each customer has one loyalty card. Create the customer, then send them addToAppleWallet or addToGoogleWallet (or cardUrl, a page with both buttons). The saved card updates by itself when stamps or points change.

POST/v1/customers

FieldTypeNotes
namestringShown on the card. Up to 60 characters.
phonestringOptional, international format. Unique per business.
externalIdstringOptional, your own id (POS customer id). Unique per business. Sending an existing one returns that customer.
branchIdstringOptional. If the branch is switched off, its cards stop.

Returns 201 for a new customer, 200 with "created": false if the phone or externalId already exists.

{
  "data": {
    "id": "cu_8f2c1e0b5a7d4c3b9e6f1a2d",
    "name": "Lina",
    "phone": "+962790000000",
    "externalId": "pos-4471",
    "branchId": "br_...",
    "stamps": 3,
    "stampTarget": 10,
    "points": 0,
    "pointsPerReward": null,
    "rewardsAvailable": 0,
    "rewardsClaimed": 1,
    "visits": 13,
    "status": "active",
    "cardUrl": "https://passhive.app/c/cu_....sig",
    "addToAppleWallet": "https://passhive.app/c/cu_....sig/apple.pkpass",
    "addToGoogleWallet": "https://passhive.app/c/cu_....sig/google",
    "createdAt": "2026-11-02T09:12:00.000Z",
    "updatedAt": "2026-11-02T10:40:00.000Z"
  }
}

GET/v1/customers?phone=+962790000000

GET/v1/customers?externalId=pos-4471

GET/v1/customers?limit=50&before=<next>

Lists newest first. Use the next value for the following page.

GET/v1/customers/{id}

Stamps, points, rewards

Stamp cards use /stamps; points cards use /points. When a card is full, a reward is added and the counter starts again. Customers get a notification on the phone.

POST/v1/customers/{id}/stamps

{ "count": 1, "branchId": "br_..." }

POST/v1/customers/{id}/points

{ "points": 25 }

POST/v1/customers/{id}/redeem

Uses one available reward. Fails with no_reward_available if there is none.

Messages

Puts an offer on saved cards. On iPhone it shows as a notification from the card; on Android Google shows it on the card with an alert. Leave out customerId to send to everyone. Limited to 3 sends a day per audience.

POST/v1/messages

{ "title": "Weekend offer", "body": "2 stamps for every coffee this Friday.", "customerId": null }

Branches

Branch locations are added to the cards (Apple: up to 10, shown near the branch on the lock screen). Your plan sets how many branches can be active.

GET/v1/branches

POST/v1/branches

{ "name": "Abdoun", "address": "Abdoun Circle, Amman", "lat": 31.9539, "lng": 35.8836 }

PATCH/v1/branches/{id}

{ "active": false }

Errors and limits

Errors return a status code and {"error": "code"}.

StatusCodeMeaning
400invalid_json, invalid_phone, invalid_amount, card_uses_pointsFix the request.
401missing_api_key, invalid_api_keyCheck the Authorization header.
402branch_limit_reachedUpgrade the plan or switch a branch off.
404customer_not_foundWrong id or another business.
429rate_limited600 requests a minute per key; 3 message sends a day.