# Get a card
Source: https://developers.perkstar.co.uk/api-reference/cards/get-a-card
/api/openapi.yaml get /cards/{id}
# List cards
Source: https://developers.perkstar.co.uk/api-reference/cards/list-cards
/api/openapi.yaml get /cards
# Anonymize (GDPR Article 17 erasure) a customer
Source: https://developers.perkstar.co.uk/api-reference/customers/anonymize-gdpr-article-17-erasure-a-customer
/api/openapi.yaml delete /customers/{id}
# Create or upsert a customer
Source: https://developers.perkstar.co.uk/api-reference/customers/create-or-upsert-a-customer
/api/openapi.yaml post /customers
When `external_ref` is supplied, the endpoint upserts on the
unique `(orgId, externalRef)` key:
• Existing match → returns the existing record with HTTP 200.
No fields are overwritten.
• No match → creates a new customer, HTTP 201.
Without `external_ref`, the endpoint always creates and returns
HTTP 201 (or 409 if the supplied email already exists in the
org). `Idempotency-Key` remains the 24h replay cache; the
externalRef upsert is the permanent semantic dedupe.
# Get a customer
Source: https://developers.perkstar.co.uk/api-reference/customers/get-a-customer
/api/openapi.yaml get /customers/{id}
# List customers
Source: https://developers.perkstar.co.uk/api-reference/customers/list-customers
/api/openapi.yaml get /customers
# Update a customer
Source: https://developers.perkstar.co.uk/api-reference/customers/update-a-customer
/api/openapi.yaml patch /customers/{id}
# Create an enrollment
Source: https://developers.perkstar.co.uk/api-reference/enrollments/create-an-enrollment
/api/openapi.yaml post /enrollments
# Get an enrollment
Source: https://developers.perkstar.co.uk/api-reference/enrollments/get-an-enrollment
/api/openapi.yaml get /enrollments/{id}
# List enrollments
Source: https://developers.perkstar.co.uk/api-reference/enrollments/list-enrollments
/api/openapi.yaml get /enrollments
# Update an enrollment
Source: https://developers.perkstar.co.uk/api-reference/enrollments/update-an-enrollment
/api/openapi.yaml patch /enrollments/{id}
# List locations
Source: https://developers.perkstar.co.uk/api-reference/locations/list-locations
/api/openapi.yaml get /locations
# Auth check + org context
Source: https://developers.perkstar.co.uk/api-reference/marketplace/auth-check-+-org-context
/api/openapi.yaml get /marketplace/ping
Confirms the API key is valid + returns the operator's org
context (name, currency, timezone) and the available cards.
First call every POS adapter makes on install.
Requires NO specific scope — any valid (non-revoked,
non-expired) key works. Brute-force / rate-limit protection
still applies.
# Find-or-create customer + enrolment (no transaction)
Source: https://developers.perkstar.co.uk/api-reference/marketplace/find-or-create-customer-+-enrolment-no-transaction
/api/openapi.yaml post /marketplace/enroll
Same identifier resolution + create-on-miss as
`/marketplace/accrue`, but without posting a transaction.
Used by checkout-time signup flows (Shopify customers/create,
Toast guest-create) where the partner wants the customer on
the loyalty programme but doesn't have a purchase to credit
yet. Idempotent on `(customer, card)` — repeating the call
returns the same enrolment at HTTP 200.
This endpoint changes live customer data and therefore rejects test
credentials with 403.
# Find-or-create customer + post transaction in one call
Source: https://developers.perkstar.co.uk/api-reference/marketplace/find-or-create-customer-+-post-transaction-in-one-call
/api/openapi.yaml post /marketplace/accrue
Resolves the customer in this fixed priority order:
1. customer_id → tenant-scoped Perkstar customer
2. card_serial → POS barcode or legacy pass serial → customer
3. external_ref → (orgId, externalRef) lookup
4. email (case-insensitive)
5. phone (normalised E.164 with a legacy raw-value fallback)
First match wins. On miss, creates a customer when
`create_customer_if_missing` is true (the default). A missing
`customer_id` alone returns 404 instead of creating a replacement.
The `transaction.external_transaction_id` field is enforced as
permanently unique per `(orgId, externalTransactionId)`. An exact
retry with the same canonical target, type, amount, and request fields
returns the existing transaction at HTTP 200 instead of
double-crediting, no matter how long has passed. Reusing the id for a
different request returns `409 external_transaction_id_conflict`. Use
this for POS-side stable ids (Toast order #s, Shopify checkout ids,
Square payment ids). Test and live transactions cannot share the same
value; a cross-environment replay is rejected with 422. Provider-owned
prefixes such as `sq_payment_` are reserved for managed integrations;
use a namespace owned by your app.
`Idempotency-Key` (24h replay cache) and
`external_transaction_id` (permanent dedupe) coexist — use
both for full robustness.
With a test credential this endpoint never creates a customer or
enrolment. Resolve an existing record and card first, then post the
isolated transaction. A missing customer or enrolment returns 404.
# Reverse a previously-posted transaction
Source: https://developers.perkstar.co.uk/api-reference/marketplace/reverse-a-previously-posted-transaction
/api/openapi.yaml post /marketplace/reverse
Creates a compensating Transaction row whose `delta` is the
negation of the original's, linked via
`reverses_transaction_id`. Fires `TRANSACTION_CREATED` so
partner webhooks notice the reversal end-to-end.
Idempotent: reversing the same transaction twice returns the
existing reversal at HTTP 200 (enforced by the unique
constraint on `Transaction.reversesTransactionId` + a P2002
fallback).
Cannot reverse:
• An already-reversed transaction's reversal (post a new
accrue instead).
• A transaction in the opposite mode — live keys can't
reverse test rows and vice versa.
Pass either `transaction_id` (Perkstar's id) OR
`external_transaction_id` (your POS-side id). Both forms
resolve to the same underlying row.
# Receive a perkstar outbound event
Source: https://developers.perkstar.co.uk/api-reference/outbound-webhooks/receive-a-perkstar-outbound-event
/api/openapi.yaml webhook perkstarEvent
Perkstar POSTs this signed envelope to each active endpoint subscribed
to the event. Client-managed integrations verify
`X-Perkstar-Signature` against the exact raw body. Approved OAuth
connectors can instead use Perkstar's server-attested verification
contract without receiving the signing secret. Persist and deduplicate
by `id`, then return a `2xx` response. Automatic retries keep the same
logical delivery `id`.
# Send a wallet push
Source: https://developers.perkstar.co.uk/api-reference/pushes/send-a-wallet-push
/api/openapi.yaml post /pushes
Sends a marketing wallet push to a specific enrolment. The
customer must have push-marketing consent enabled, otherwise
the endpoint returns 403 with
`push_marketing_consent_required`.
Merge fields (`{firstName}`, `{balance}`, `{installLink}`,
`{shareLink}`, `{cardName}`, `{orgName}`) are resolved against
the targeted customer + enrolment + card.
Throttle: 3-minute per-card cooldown. Hit → 429 with
`Retry-After`. The cooldown is shared with the operator's
dashboard push paths so a rapid dashboard + API sequence is
also caught.
Test mode (`pk_test_…` or OAuth `mode=TEST`): the endpoint
returns 200 with `test_mode: true` but does NOT push. Lets
partners verify wire integration without spamming real
customer lock screens.
Requests without `Idempotency-Key` return 400 with the stable
error code `idempotency_key_required` and no Wallet mutation.
# Bulk-delete every test-mode transaction for the org
Source: https://developers.perkstar.co.uk/api-reference/transactions/bulk-delete-every-test-mode-transaction-for-the-org
/api/openapi.yaml delete /transactions/test
Sandbox cleanup. Requires a `pk_test_…` key — live keys are
rejected with 403. Returns the row count deleted. Aggregates
on Customer / Card / Enrollment do not need recomputing
because test rows never contributed to them.
# List transactions
Source: https://developers.perkstar.co.uk/api-reference/transactions/list-transactions
/api/openapi.yaml get /transactions
# Post a transaction (stamp / redeem / adjust)
Source: https://developers.perkstar.co.uk/api-reference/transactions/post-a-transaction-stamp-redeem-adjust
/api/openapi.yaml post /transactions
# Create a webhook
Source: https://developers.perkstar.co.uk/api-reference/webhooks/create-a-webhook
/api/openapi.yaml post /webhooks
Direct API-key requests use the normal 24-hour idempotency response
cache. For OAuth REST-hook clients, the idempotency key remains bound
to the live subscription until DELETE. A retry with the same event set
returns that row; use PATCH to apply a current URL, card, mode, or active
state. `client_hmac` subscriptions return their signing secret on create
and OAuth idempotent replay. OAuth-only `server_attested` subscriptions
keep the signing secret inside Perkstar and omit it from every response.
Reusing the key for a different event set or verification mode returns
an idempotency conflict.
# Delete a webhook
Source: https://developers.perkstar.co.uk/api-reference/webhooks/delete-a-webhook
/api/openapi.yaml delete /webhooks/{id}
# Get a webhook
Source: https://developers.perkstar.co.uk/api-reference/webhooks/get-a-webhook
/api/openapi.yaml get /webhooks/{id}
# List recent outbound events
Source: https://developers.perkstar.co.uk/api-reference/webhooks/list-recent-outbound-events
/api/openapi.yaml get /events
Returns one canonical row per source event, newest first. REST-hook
integrations use this endpoint to load representative sample data
whose keys and types match the live webhook envelope. Live events are
returned by default; request `mode=test` or `mode=all` explicitly when
validating sandbox activity. Event rows are retained for 90 days and
require the dedicated `EVENTS_READ` scope.
# List webhooks
Source: https://developers.perkstar.co.uk/api-reference/webhooks/list-webhooks
/api/openapi.yaml get /webhooks
# Update a webhook
Source: https://developers.perkstar.co.uk/api-reference/webhooks/update-a-webhook
/api/openapi.yaml patch /webhooks/{id}
# Verify a server-attested webhook delivery
Source: https://developers.perkstar.co.uk/api-reference/webhooks/verify-a-server-attested-webhook-delivery
/api/openapi.yaml post /webhooks/deliveries/verify
OAuth-only callback proof endpoint for approved automation connectors.
It binds the parsed event and retention-bounded Perkstar delivery headers to
the exact outbound attempt committed before dispatch. Authenticated
proof failures deliberately return the same `{ "verified": false }`
response so webhook IDs, delivery IDs, and proof state cannot be
enumerated. Ordinary client-managed HMAC integrations do not use this
endpoint.
# Changelog
Source: https://developers.perkstar.co.uk/changelog
Developer-facing changes to the Perkstar API, SDK, and integration guidance.
## 13 September 2026 — Resend and integration setup guides
* Connect your own Resend account inside the integration workspace for supported invitations and card-install emails.
* Follow the signed delivery test before choosing when to activate; a failed own-account connection never falls back to Perkstar's shared sender.
* Find every provider in the integration directory, with setup guides for available connections and explicit availability notes for limited or unreleased providers.
* Browse guides by task, with detailed provider sections grouped in the sidebar.
See [Resend setup](/integrations/resend/setup) and the [integration directory](/integrations).
## August 2026
### Loyverse existing-customer migration
* Added a guided transfer that reads the current Loyverse customer directory,
copies each current points balance to the exact Perkstar membership and
continues safely in the background without requiring a merchant CSV.
* Added a default-off, owner-only choice to give eligible existing customers
the selected card's normal welcome points. Perkstar shows the maximum points,
cash-equivalent exposure and expiry before confirmation, then keeps the
choice fixed across retries and reconnects.
* Added business-controlled migration invitations: an included service email,
paid SMS after subscription activation and credit purchase, or both. Known
Loyverse contact details stay locked to the migrated membership so customers
cannot accidentally claim an empty duplicate account.
* Added readiness gates, retry-safe results and explicit migration timing for
larger customer lists. Invitations, scanning and till redemption remain
unavailable until the relevant preceding checks are complete.
* Added Teya camera and SUNMI Blink guidance, including the requirement to test
USB HID/keyboard and host/OTG support on the exact terminal or dock.
* Made the saved Loyverse card unmistakable, including conservative confirmation
when a paid poster order can be tied to the unchanged card design, and removed
the extra card-creation prompt once a compatible card is saved.
* Added explicit prerequisite lists beside unavailable setup actions, a direct
Step 2 guide link and actionable missing-permission connection errors.
* Added redacted, support-visible Step 2 attempt references plus a one-click
setup diagnostic snapshot that excludes customer details, individual
balances, tokens and raw provider errors.
* Added a one-recipient migration rehearsal over included email or paid SMS,
with exact recipient, message and credit confirmation before the business
releases either remaining audience.
### Zapier public Beta
* Perkstar version 1.0.0 is now available in [Zapier's public App
Directory](https://zapier.com/apps/perkstar/integrations); a Zapier invitation
is no longer required.
* Added a direct public connection path, clarified that one OAuth connection
represents one Perkstar business and can be reused across multiple Zaps, and
documented separate connections for additional businesses.
* Split support ownership between Perkstar connection/API issues, Zapier
account/editor issues, and failures in other connected apps.
* Added a self-serve Zapier page in the Perkstar integration settings with
public directory, setup-guide, and safe app-pairing links.
* Submitted five launch templates to Zapier review. A sixth Square template is
held in Draft until a customer-attributed sample verifies its buyer-email
mapping; customer-facing template links will be added only after approval.
* Replaced invite-only setup and troubleshooting guidance throughout the
developer portal. The earlier pre-release notes below describe the state
before publication.
### Make private-beta package
* Added a source-controlled Make custom app with tenant-scoped OAuth 2.0,
PKCE, rotating refresh tokens, and an attached instant webhook.
* Added one **Watch a Loyalty Event** module covering all 29 public business
events, 11 guided actions, two paginated searches, five filtered Card
selectors, and the required fixed-origin **Make an API Call** module.
* Added seven self-serve guides covering setup, the full module catalogue,
recipes, webhook delivery, troubleshooting, privacy, and security.
* Documented the eight default OAuth permissions, five optional advanced
permissions, retry-safe writes, rate-limit handling, and server-attested
webhook verification that keeps signing secrets inside Perkstar.
* The app remains private while live scenarios and Make review evidence are
completed; it is not yet available in Make's public catalogue.
### Zapier pre-release package (historical)
* Added source-ready documentation for Perkstar's first-party Zapier app.
* Documented OAuth connection, Growth-and-above eligibility, and the
private-invitation boundary before public App Directory review. Private
version 1.0.0 is registered and available to invited Zapier accounts, but is
not yet listed publicly.
* Expanded the complete named instant-trigger catalogue to 29 business events;
the diagnostic `webhook.test` event remains excluded.
* Added `wallet.installed`, `card.scanned`, `card.expired`,
`customer.group_changed`, and `referral.created`, with explicit provider,
online-scanner, per-enrolment expiry, lifecycle-group, and customer-referral
boundaries.
* Documented all 10 visible actions, two searches, both explicit
Search-or-Create relationships, the dynamic card selector, webhook retry
identity, recipes, troubleshooting, and data-handling model.
* Added direct Customer ID lookup to **Find Customer** so trigger records can be
enriched without matching personal identifiers again.
* Bound each permanent loyalty Source ID to its first canonical request; an
exact retry replays safely, while changed customer/card/operation inputs now
return `409 external_transaction_id_conflict`.
* Documented the one-sweep warm-up boundary for a business's first lifecycle
group or Google-install trigger; Apple installation remains callback-driven.
* Added the dedicated `EVENTS_READ` permission for the bounded 90-day sample
feed, without broadening existing `WEBHOOKS_READ` credentials.
* Documented signed callback verification and the app-managed subscription
lifecycle; Zapier-owned hooks cannot be edited, rotated, or deleted from the
custom-webhook dashboard.
## July 2026
### Developer portal
* Added a dedicated guide and generated API reference for integration teams.
* Added production recipes for POS, Odoo, customer sync, webhooks, and wallet pushes.
* Added a security and operational go-live checklist.
* Added the official Python SDK with retries, pagination, typed errors, and webhook verification.
* Added a generated Postman collection and production environment covering all public v1 operations.
* Added a public component status page and machine-readable status endpoint.
### API key safety
* Direct API-key presets no longer include the internal OAuth-only MCP scope.
* MCP access now explicitly requires an OAuth token.
* Test keys cannot mutate customers, enrolments, or webhook configuration.
* Test marketplace accrual is restricted to existing customers and enrolments.
* Direct browser playground calls accept only approved Perkstar developer-portal origins.
### Documentation contract
* Test-mode limitations are now part of the canonical OpenAPI description.
* Documentation navigation and links are validated in CI.
* SDK packages, Postman assets, and OpenAPI operation coverage are validated before release.
## May 2026
* Added the v1 REST API, scoped API keys, OAuth access tokens, cursor pagination, and request tracing.
* Added POS-friendly marketplace ping, accrue, enrol, and reverse endpoints.
* Published the official zero-dependency TypeScript SDK.
# Authentication and scopes
Source: https://developers.perkstar.co.uk/fundamentals/authentication
Protect API credentials and grant only the permissions an integration needs.
Perkstar accepts a bearer credential in the `Authorization` header:
```http theme={null}
Authorization: Bearer pk_live_...
```
Direct integrations use an API key. Marketplace applications use OAuth access
tokens beginning with `perk_at_`. Both credential types use the same endpoint
shapes and error format.
The public [Perkstar app for Zapier](/integrations/zapier) uses Perkstar
OAuth. Users approve the hosted consent screen and never copy a raw Perkstar
API key into a Zap field.
## API key environments
| Prefix | Intended use | Live-data writes |
| - | - | - |
| `pk_test_` | Development and certification | Only isolated test transactions and simulated pushes |
| `pk_live_` | Production traffic | Allowed when the key has the required scope |
The environment is part of the signed secret. Renaming or rotating a key does
not change its environment.
## Available direct-key scopes
| Scope | Allows |
| - | - |
| `CUSTOMERS_READ` | Find and list customers |
| `CUSTOMERS_WRITE` | Create, update, or anonymise customers |
| `ENROLLMENTS_READ` | Read loyalty enrolments and balances |
| `ENROLLMENTS_WRITE` | Create or update enrolments |
| `TRANSACTIONS_READ` | Read live or test ledger rows |
| `TRANSACTIONS_WRITE` | Post stamps, redeems, and adjustments |
| `CARDS_READ` | Read card configuration |
| `EVENTS_READ` | Read the recent loyalty-event feed |
| `WEBHOOKS_READ` | Inspect webhook endpoints |
| `WEBHOOKS_WRITE` | Create, edit, or remove webhook endpoints |
| `LOCATIONS_READ` | Map Perkstar locations to external systems |
| `PUSHES_WRITE` | Send or simulate a wallet push |
| `MARKETPLACE` | Use the POS-friendly marketplace endpoints |
Test keys cannot be granted `CUSTOMERS_WRITE`, `ENROLLMENTS_WRITE`, or
`WEBHOOKS_WRITE`. The `MCP` permission is internal to OAuth consent and is never
available to direct API keys.
## Least-privilege examples
* **Read-only reporting:** customers read, enrolments read, transactions read, cards read.
* **POS till:** marketplace and locations read.
* **CRM sync:** customers read/write and enrolments read/write.
* **Wallet messaging:** customers read, enrolments read, pushes write.
* **Webhook consumer setup:** webhooks read/write; add events read only when it needs the recent-event feed.
## Credential handling
1. Keep keys in an encrypted server-side secret store.
2. Use separate keys for each integration and environment.
3. Give each key a name that identifies its owner and purpose.
4. Set an expiry where the integration can rotate automatically.
5. Rotate immediately after accidental exposure or team-member departure.
6. Revoke unused keys rather than leaving them dormant.
Never send an API key to a browser or expose it in a public Odoo client
action. Calls must originate from trusted server code.
The hosted API request builder is for short-lived testing with a test key on a
trusted device. Do not enter a live key on a shared computer, and never copy its
browser-based request pattern into a customer-facing application.
# Errors and request tracing
Source: https://developers.perkstar.co.uk/fundamentals/errors
Handle Perkstar API failures consistently and give support enough detail to trace them.
API errors use one predictable envelope:
```json theme={null}
{
"error": {
"type": "validation_error",
"code": "invalid_request_body",
"message": "The request body is invalid.",
"param": "transaction.type"
}
}
```
## Status codes
| Status | Meaning |
| - | - |
| `400` | Malformed JSON or invalid request shape |
| `401` | Missing, invalid, expired, or revoked credential |
| `403` | The key lacks a scope, plan access, or live-write permission |
| `404` | The requested record does not exist in this business |
| `409` | The request conflicts with existing data or idempotency state |
| `410` | The key or business has been permanently closed or revoked |
| `422` | The request is valid JSON but incompatible with the card or balance |
| `429` | The key exceeded its rate limit |
| `5xx` | Perkstar could not complete an otherwise valid request |
## Universal response headers
Every success and error includes:
* `X-Request-Id`: the exact request reference for logs and support.
* `X-API-Version`: the date-versioned contract served by the endpoint.
* `X-RateLimit-Limit`: the credential's current per-minute allowance.
* `X-RateLimit-Remaining`: calls left in the current window.
* `X-RateLimit-Reset`: Unix seconds when the window resets.
* `Retry-After`: seconds to wait after a `429`.
Log the request ID, endpoint, status, error code, and your own operation ID. Do
not log bearer credentials, full customer payloads, or webhook secrets.
## Unknown outcomes
If the connection drops after a POST, treat the result as unknown rather than
failed. Retry with the same `Idempotency-Key`. For POS transactions, send the
same `external_transaction_id` as well.
`400 reserved_external_transaction_id` means the identifier used a namespace
owned by a managed POS integration. Choose a stable prefix belonging to your
app and retry with a new identifier.
## Contacting support
Email [support@perkstar.co.uk](mailto:support@perkstar.co.uk) with:
1. `X-Request-Id`;
2. UTC timestamp;
3. HTTP method and path;
4. response status and error code; and
5. the first 12-character key prefix shown in the dashboard.
Never include the full API key or personal customer data.
# Idempotency and retries
Source: https://developers.perkstar.co.uk/fundamentals/idempotency
Retry requests without adding the same stamp, point award, or enrolment twice.
Networks fail in awkward places. A timeout does not tell you whether Perkstar
accepted a request, so every production integration must be safe to retry.
## Request idempotency
Send an `Idempotency-Key` with every POST request:
```http theme={null}
Idempotency-Key: order-94721-loyalty-v1
```
Use a stable value for one logical operation, not a new random value on each
retry. Perkstar keeps the result for 24 hours and returns the same outcome when
the same request is repeated.
OAuth REST-hook creation has a resource-lifecycle exception. For `POST
/webhooks`, the idempotency key remains bound to the live subscription until
that row is deleted, and a retry returns its signing secret. The event set
must stay the same; apply a current callback URL, card, live/test mode, or
active state with `PATCH /webhooks/:id`. Deleting the subscription releases
the key immediately.
Reusing one key for a different request body is an integration error. Create a
new key only when you intend to perform a new operation.
## Permanent transaction deduplication
POS and commerce integrations should also send
`transaction.external_transaction_id` to `/marketplace/accrue`.
```json theme={null}
{
"transaction": {
"type": "STAMP",
"external_transaction_id": "odoo-pos-order-94721"
}
}
```
This reference is unique for the business and remains a deduplication key after
the 24-hour request cache expires. A repeated call returns the existing
transaction with `idempotent_replay: true`.
Use an upstream ID that is:
* stable across webhook retries;
* unique to one loyalty operation;
* available again when a refund must reverse the operation; and
* namespaced when several stores can produce the same numeric order ID.
Good: `odoo:shop_12:pos_order:94721`
Risky: `94721`
Keep test and live references in separate namespaces, for example
`test:odoo:shop_12:pos_order:94721` and
`live:odoo:shop_12:pos_order:94721`. Perkstar rejects a permanent transaction
reference that already belongs to the other environment instead of silently
replaying it.
## Retry policy
| Result | Action |
| - | - |
| Network error or timeout | Retry with the same idempotency key |
| `429` | Wait for `Retry-After`, then retry |
| `500`, `502`, `503`, `504` | Retry with exponential backoff and jitter |
| `400`, `403`, `404`, `409`, `422` | Fix the request or state; do not blindly retry |
| `401` | Replace or rotate the credential before retrying |
A practical schedule is 1 second, 2 seconds, 4 seconds, then a background retry
queue. Cap attempts and surface terminal failures for an operator to inspect.
## Reversals
Reverse a transaction by Perkstar ID or by its original
`external_transaction_id`. Give the reversal its own idempotency key. Test and
live transactions cannot be reversed across environments. Use an identifier
namespace owned by your integration; provider-managed prefixes such as
`sq_payment_` are reserved.
# Pagination
Source: https://developers.perkstar.co.uk/fundamentals/pagination
Traverse large customer, enrolment, transaction, card, and webhook collections safely.
List endpoints use cursor pagination. A response has this shape:
```json theme={null}
{
"data": [],
"has_more": true,
"next_cursor": "cmexample",
"limit": 100
}
```
Pass `next_cursor` back as `cursor`:
```bash theme={null}
curl "$PERKSTAR_API_URL/customers?limit=100&cursor=cmexample" \
--header "Authorization: Bearer $PERKSTAR_API_KEY"
```
## Rules
* Treat cursors as opaque strings. Do not parse or increment them.
* Stop when `has_more` is false or `next_cursor` is null.
* Keep the same filters while following a cursor.
* Process each page before requesting the next one to avoid memory spikes.
* Checkpoint the last completed cursor in long-running backfills.
* Make your destination writes idempotent because records can change during a scan.
Cursor pagination is not a frozen database snapshot. For ongoing sync, store
Perkstar record IDs and `updated_at` values, and use webhooks to react to new
activity between reconciliation runs.
## TypeScript SDK
The official SDK follows cursors automatically:
```ts theme={null}
for await (const customer of perkstar.customers.list({ limit: 100 })) {
await upsertCustomer(customer);
}
```
# Security, privacy, and data handling
Source: https://developers.perkstar.co.uk/fundamentals/security-privacy
Understand Perkstar's security boundaries, privacy roles, retention rules, and integration responsibilities.
This page is the technical data-handling summary for teams integrating with
Perkstar. The [Privacy Notice](https://dashboard.perkstar.co.uk/privacy),
[Data Processing Agreement](https://dashboard.perkstar.co.uk/dpa), and
[sub-processor list](https://dashboard.perkstar.co.uk/dpa/sub-processors) are
the governing documents.
This page explains product behaviour; it is not legal advice and does not
replace your own privacy, security, or regulatory review.
## Responsibility model
```mermaid theme={null}
flowchart LR
Customer["Cardholder"] --> Business["Business using Perkstar\nNormally the data controller"]
Business --> Perkstar["Perkstar\nNormally the data processor"]
Perkstar --> Provider["Approved sub-processors\nand enabled integrations"]
Partner["Your integration"] <--> Perkstar
Business --> Partner
```
For cardholder loyalty data, the business normally decides why data is
processed, what is collected, which messages are sent, and which integrations
are enabled. Perkstar normally processes that data for the business. Perkstar
acts as controller for limited platform purposes such as account
administration, billing, support, security, fraud prevention, and legal
compliance.
Your organisation is responsible for determining its role for data copied to
or from its integration, documenting a lawful purpose, and honouring deletion,
access, correction, consent, and objection requests.
## Data an integration can handle
| Category | Typical fields | Minimise it by |
| - | - | - |
| Customer identity | Name, email, phone, date of birth, external reference | Requesting only the scopes and fields needed for the workflow |
| Loyalty activity | Card, enrolment, balance, transaction, reward and redemption records | Storing Perkstar IDs instead of duplicating full profiles |
| Consent | Marketing and ad-tracking flags, consent history | Treating flags as purpose-specific evidence, not blanket permission |
| Location and commerce context | Location ID, amount, order or transaction reference | Sending stable references and required totals, not full baskets by default |
| Credentials | API keys, OAuth access/refresh tokens, webhook secrets | Keeping secrets in a server-side secret manager and never in client code |
| Operational metadata | Request IDs, status codes, delivery IDs, timestamps | Avoiding raw payloads in logs unless needed and access-controlled |
## Security boundaries
Credentials resolve to one organisation. Resource queries and mutations are
checked against that organisation at the API boundary.
API keys and OAuth grants carry explicit scopes. Create a separate
credential for each integration and environment.
API keys, client secrets, authorization codes, and OAuth tokens are stored
as non-reversible hashes where they only need comparison. Provider
credentials that must be reused are encrypted.
Production traffic uses HTTPS. OAuth redirect URIs match exactly; webhooks
are HMAC signed and outbound URLs are checked against private-network and
DNS-rebinding targets.
POST requests use idempotency keys, POS transactions support permanent
external-reference deduplication, and OAuth refresh tokens rotate once.
API responses include `X-Request-Id`; authenticated API activity is kept in
a bounded audit trail for investigation and support.
## Credential handling
1. Create separate test and live credentials.
2. Grant only the scopes required by the job.
3. Store plaintext secrets immediately; Perkstar cannot reveal them again.
4. Never place a key or client secret in browser JavaScript, a mobile bundle,
source control, analytics, screenshots, or support messages.
5. Rotate on suspected exposure and revoke credentials when an integration is
disconnected.
6. Treat webhook bodies and OAuth tokens as personal or confidential data when
they can be linked to a customer or business.
See [Authentication and scopes](/fundamentals/authentication) and the
[OAuth marketplace guide](/guides/oauth-marketplace) for implementation
details. Businesses preparing to use the no-code connector should also read
[Zapier data and security](/integrations/zapier/data-security) for its specific
downstream data flow and deletion boundaries.
## Consent and communications
Customer profile fields and consent flags can be written by an authorised
integration. Perkstar records each real API consent transition, including the
calling credential and request context, in its consent audit trail. That event
records what the integration asserted; it does not prove that your external
system collected valid consent. Keep the source, wording, time, and lawful
basis needed for your own audit.
Marketing wallet pushes require push-marketing consent. Transactional wallet
updates needed to keep a pass accurate are separate from promotional
communications. Do not infer email or SMS permission from a wallet install.
## Retention and deletion
| Record | Current operational rule |
| - | - |
| Active customer profile | Kept while the operator account and loyalty relationship are active |
| Cancelled-account cardholder data | 90-day grace period, then anonymised or deleted where no legal hold applies |
| Pseudonymised transaction residue | Up to the applicable accounting/legal period, usually up to six years for UK operators |
| Data-export archive | Expires after 48 hours and uses a single-use link |
| Security and rate-limit logs | Normally 90 days unless required for an investigation |
| API request audit | Rolling seven-day operational window |
| Production backups | Rolling seven days |
| Marketing suppression evidence | Kept as needed to prevent accidental re-contact |
Customer erasure is implemented as anonymisation when financial or audit facts
must remain. Direct identifiers are removed while the minimum pseudonymised
ledger can be retained. `DELETE /customers/{id}` exposes that workflow to a
properly scoped integration.
Deleting data from your integration does not delete it from Perkstar, and
anonymising it in Perkstar does not automatically erase an uncontrolled copy
in your system. Design and test propagation in both directions.
## Webhook and OAuth data
* Verify webhook signatures against the exact raw body before parsing.
* Deduplicate with the stable webhook event ID and restrict access to stored
delivery payloads.
* OAuth access tokens expire after one hour. Refresh tokens rotate and must be
replaced atomically; replay revokes the grant.
* Revoking either an access or refresh token revokes the paired grant.
* A marketplace uninstall should stop jobs, revoke tokens, remove unnecessary
cached personal data, and retain only the audit facts your policy requires.
## Rights requests and incidents
Businesses can export and anonymise customer data in the dashboard, and
customers can use the privacy controls linked from their pass. Integration
teams should be able to locate records by Perkstar ID and external reference,
export a readable copy, correct a mismatch, and erase or suppress downstream
copies.
Report suspected credential exposure, unauthorised access, or a personal-data
incident immediately to [privacy@perkstar.co.uk](mailto:privacy@perkstar.co.uk).
For API implementation support, contact
[support@perkstar.co.uk](mailto:support@perkstar.co.uk) with the relevant
`X-Request-Id`, never a secret.
## Production review
* [ ] Data flow, role, purpose, and lawful basis are documented.
* [ ] Test data is separated from live credentials and jobs.
* [ ] Secrets are stored server-side and rotation is tested.
* [ ] Webhook verification, deduplication, and retention are tested.
* [ ] OAuth disconnect and refresh-token replay are handled.
* [ ] Customer export, correction, deletion, and suppression propagate.
* [ ] Logs redact secrets and unnecessary personal data.
* [ ] The DPA and sub-processor list have been reviewed.
# Test mode
Source: https://developers.perkstar.co.uk/fundamentals/test-mode
Exercise an integration without changing live customer balances or configuration.
Test mode uses a `pk_test_` key or an OAuth application registered in TEST mode.
It shares the production API shape, but write behaviour is deliberately narrow.
## What a test key can do
* Read cards, locations, customers, enrolments, transactions, and webhook configuration.
* Create test ledger transactions against an existing enrolment.
* Call `/marketplace/accrue` for an existing customer and existing enrolment.
* Simulate wallet pushes without delivering a notification.
* Receive signed transaction webhooks marked with `testMode: true`.
* List and clean up test transactions.
## What it cannot do
* Create, update, or anonymise a live customer.
* Create or change a live enrolment.
* Create, edit, or delete webhook configuration.
* Use `/marketplace/enroll`.
* Create a customer or enrolment as a side effect of `/marketplace/accrue`.
* Deliver a real wallet push.
These restrictions apply on the server even if an older key row contains an
unsafe scope. The dashboard also removes unsupported scopes when a test key is
created or edited.
## Testing a POS transaction
1. Use `GET /customers` or a scanned `card_serial` to resolve a customer.
2. Use `GET /enrollments` to find the matching card enrolment.
3. Post the transaction with a stable `external_transaction_id`.
4. Confirm the response includes `test_mode: true`.
5. Confirm your webhook receiver branches on `testMode`.
Prefix test transaction references with `test:`. The same permanent reference
cannot be reused later for a live transaction.
To remove all test ledger rows after certification:
```bash theme={null}
curl --request DELETE \
"https://dashboard.perkstar.co.uk/api/v1/transactions/test" \
--header "Authorization: Bearer $PERKSTAR_API_KEY"
```
Test reads return the business's current records so an integration can prove
its matching logic. Treat test keys as sensitive because those records can
contain personal data.
# Synchronise customers
Source: https://developers.perkstar.co.uk/guides/customer-sync
Match customer records without duplicates and preserve consent correctly.
Use a stable upstream identifier whenever possible. Email addresses and phone
numbers can change, be shared, or be entered differently across systems.
## Identity strategy
`external_ref` is unique within a Perkstar business. Namespace the value when
more than one source or account can produce the same native ID:
```text theme={null}
odoo:company_4:partner_981
shopify:shop_12:customer_981
```
When `POST /customers` includes an `external_ref`:
* an existing match is returned with `200` and is not overwritten;
* a missing match is created with `201`; and
* retries remain safe beyond the request idempotency window.
## Initial import
1. Page through the source system in stable order.
2. Upsert each customer with `external_ref`.
3. Store the returned Perkstar customer ID in the source system.
4. Checkpoint progress after each completed page.
5. Run a second pass for records changed during the import.
Limit concurrency and respect Perkstar's rate-limit headers. A large import
should use a durable job queue, not one browser request.
## Consent
Consent is not a convenience flag. Set `consent_marketing` or
`consent_ad_tracking` only when the source system contains a valid, auditable
permission for that purpose. A blank source value should not become `true`.
## Updates and deletion
* Send PATCH only for fields your integration owns.
* Normalise upstream phone numbers before matching where possible.
* Treat a Perkstar anonymisation response as permanent.
* Do not recreate an anonymised person automatically from a stale export.
* Keep API keys and personal payloads out of logs.
Test keys can read customer records but cannot create, edit, or anonymise
them. Perform customer writes only after certification with a live key that
has `CUSTOMERS_WRITE`.
# Build an OAuth marketplace app
Source: https://developers.perkstar.co.uk/guides/oauth-marketplace
Implement installation, consent, token rotation, revocation, and reconnect for a multi-merchant Perkstar integration.
Use OAuth when one application will be installed by multiple Perkstar
businesses. Each merchant approves access to one organisation; your backend
receives a scoped, short-lived access token and a rotating refresh token.
```mermaid theme={null}
sequenceDiagram
participant M as Merchant
participant A as Partner app
participant P as Perkstar OAuth
participant API as Perkstar API
M->>A: Select Install Perkstar
A->>A: Create state + PKCE verifier
A->>P: GET /oauth/authorize
P->>M: Sign in, choose business, review scopes
M->>P: Allow
P-->>A: callback?code=...&state=...
A->>P: Exchange code + verifier
P-->>A: Access token + rotating refresh token
A->>API: Bearer perk_at_...
API-->>A: Organisation-scoped response
```
## Supported profile
| Capability | Perkstar behaviour |
| - | - |
| Authorization flow | Authorization Code |
| PKCE | Required, `S256` only |
| Access token lifetime | 3,600 seconds |
| Refresh tokens | Single-use rotation; replay revokes the grant |
| Redirect URIs | Exact match; HTTPS except loopback development callbacks |
| Client authentication | HTTP Basic or form secret for confidential apps |
| Merchant approver | Organisation owner or manager |
| Revocation | RFC 7009-style endpoint; unknown tokens still return `200` |
Perkstar does not support an implicit flow or a marketplace
`client_credentials` grant. A merchant must approve access to their business.
## 1. Register the application
Marketplace applications are reviewed and registered by Perkstar. Send
[support@perkstar.co.uk](mailto:support@perkstar.co.uk):
* application name, description, and HTTPS icon URL;
* exact development, staging, and production redirect URIs;
* the minimum scopes required;
* a security/support contact and uninstall URL; and
* whether the application is ready for test or live merchants.
Perkstar returns a `client_id` and shows the `client_secret` once. Store the
secret in your backend's secret manager. Dynamic client registration at
`/api/oauth/register` is reserved for read-only MCP clients and cannot register
a marketplace app or request REST API scopes.
## 2. Create state and PKCE
Create a fresh verifier, challenge, and state for every install attempt. Store
the verifier and state in a short-lived, single-use server-side record tied to
the browser session.
```ts TypeScript theme={null}
import { createHash, randomBytes } from "node:crypto";
const base64url = (value: Buffer) => value.toString("base64url");
const verifier = base64url(randomBytes(48));
const challenge = createHash("sha256").update(verifier).digest("base64url");
const state = base64url(randomBytes(32));
```
```python Python theme={null}
import base64
import hashlib
import secrets
def b64url(value: bytes) -> str:
return base64.urlsafe_b64encode(value).rstrip(b"=").decode()
verifier = b64url(secrets.token_bytes(48))
challenge = b64url(hashlib.sha256(verifier.encode()).digest())
state = b64url(secrets.token_bytes(32))
```
## 3. Send the merchant to consent
```text theme={null}
https://dashboard.perkstar.co.uk/oauth/authorize
?response_type=code
&client_id=oac_replace_me
&redirect_uri=https%3A%2F%2Fintegration.example.com%2Foauth%2Fperkstar%2Fcallback
&scope=CUSTOMERS_READ%20ENROLLMENTS_READ%20TRANSACTIONS_WRITE
&state=random_single_use_state
&code_challenge=base64url_sha256_challenge
&code_challenge_method=S256
```
The merchant signs in, chooses an organisation they own or manage, and sees the
requested permissions. Perkstar does not redirect to an unregistered URI when
the request is invalid.
## 4. Validate the callback
On success, Perkstar redirects to the exact registered URI with `code` and the
original `state`. On denial it returns `error=access_denied` and the state.
1. Compare `state` in constant time with the stored, unused value.
2. Refuse missing, mismatched, expired, or already-used state.
3. Mark the install attempt consumed before exchanging the code.
4. Never log the authorization code or callback query string.
Authorization codes are short-lived and single-use. A duplicate or delayed
callback must start a fresh install.
## 5. Exchange the code
The token endpoint accepts form-encoded bodies, not JSON.
```bash theme={null}
curl --request POST https://dashboard.perkstar.co.uk/api/oauth/token \
--user "$PERKSTAR_CLIENT_ID:$PERKSTAR_CLIENT_SECRET" \
--header "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=authorization_code" \
--data-urlencode "code=$PERKSTAR_AUTHORIZATION_CODE" \
--data-urlencode "redirect_uri=https://integration.example.com/oauth/perkstar/callback" \
--data-urlencode "code_verifier=$PERKSTAR_CODE_VERIFIER"
```
```json theme={null}
{
"access_token": "perk_at_example",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "perk_rt_example",
"scope": "CUSTOMERS_READ ENROLLMENTS_READ TRANSACTIONS_WRITE",
"organization_id": "org_123"
}
```
Store the organisation ID with the grant and enforce one active installation
record per `(application, organization_id)` in your system.
## 6. Call the API
```bash theme={null}
curl https://dashboard.perkstar.co.uk/api/v1/marketplace/ping \
--header "Authorization: Bearer $PERKSTAR_ACCESS_TOKEN"
```
Treat a `401` as an authentication problem, not permission to switch to another
merchant's token. A `403` means the authenticated grant, scope, plan, or account
state does not permit that action.
## 7. Rotate refresh tokens atomically
Every successful refresh invalidates the supplied refresh token and returns a
new one. Use a lock or compare-and-swap around the installation row.
```bash theme={null}
curl --request POST https://dashboard.perkstar.co.uk/api/oauth/token \
--user "$PERKSTAR_CLIENT_ID:$PERKSTAR_CLIENT_SECRET" \
--header "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=refresh_token" \
--data-urlencode "refresh_token=$PERKSTAR_REFRESH_TOKEN"
```
Ensure two workers cannot refresh the same grant concurrently.
Send the token stored on the locked row. Do not retry an ambiguous refresh
concurrently from another worker.
Replace the access token, refresh token, expiry, and scopes in one database
transaction before releasing the lock.
Refresh-token replay revokes the chain. Stop background jobs and send the
merchant through authorization again; do not loop retries.
## 8. Revoke and uninstall
```bash theme={null}
curl --request POST https://dashboard.perkstar.co.uk/api/oauth/revoke \
--header "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "client_id=$PERKSTAR_CLIENT_ID" \
--data-urlencode "client_secret=$PERKSTAR_CLIENT_SECRET" \
--data-urlencode "token=$PERKSTAR_REFRESH_TOKEN" \
--data-urlencode "token_type_hint=refresh_token"
```
Revoking either token revokes the pair. After a successful uninstall:
* stop polling, queue drains, and webhook side effects for the merchant;
* remove active credentials from normal application storage;
* delete copied personal data that is no longer required;
* retain only the minimum audit or legal record required by your policy; and
* make reinstall create a fresh grant rather than reviving old credentials.
Merchants can also revoke access in **Settings → Connected apps**. Your jobs
must handle that without relying on your own uninstall screen being called.
## Error handling
| Error | Meaning | Partner action |
| - | - | - |
| `invalid_request` | Missing parameter or wrong content type | Correct the request; do not retry unchanged |
| `invalid_client` | Client ID/secret failed | Stop and check configuration or secret rotation |
| `invalid_grant` | Code/token expired, used, revoked, mismatched, or replayed | Start a fresh merchant authorization |
| `invalid_scope` | No still-allowed scope remains | Review app registration and requested scopes |
| `unsupported_grant_type` | Flow is not authorization code or refresh token | Correct the implementation |
| `temporarily_unavailable` | Rate-limit or transient gate | Honour backoff and retry safely |
## Launch checklist
* [ ] Redirect URIs are exact and environment-specific.
* [ ] State and PKCE are fresh, server-stored, expiring, and single-use.
* [ ] Client secrets and tokens never reach browser or mobile code.
* [ ] Refresh replacement is atomic and concurrency-tested.
* [ ] `invalid_grant`, merchant denial, and revocation lead to a clear reconnect state.
* [ ] Jobs are pinned to the stored `organization_id`.
* [ ] Uninstall removes credentials and unnecessary cached personal data.
* [ ] Test and live application credentials are separated.
* [ ] The [security and privacy review](/fundamentals/security-privacy) is complete.
# Connect Odoo
Source: https://developers.perkstar.co.uk/guides/odoo
A production pattern for syncing Odoo contacts and POS orders with Perkstar.
Build the connector as an Odoo server module or trusted middleware service. Do
not call Perkstar directly from browser-side Odoo code because that would expose
the API key.
## Recommended mapping
| Odoo | Perkstar | Rule |
| - | - | - |
| Company + `res.partner.id` | `customer.external_ref` | `odoo::partner:` |
| POS order ID | `external_transaction_id` | `odoo::pos_order:` |
| POS location | `metadata.locationId` | Store the Perkstar location UUID on the Odoo shop config |
| Loyalty programme | `card_id` | Explicit mapping; do not infer when several cards exist |
| Refund ID | reversal idempotency key | One stable key per refund operation |
## Contact sync
When an Odoo contact becomes eligible for loyalty, call `POST /customers` with
`external_ref`. That endpoint upserts on the external reference: a retry returns
the existing customer without overwriting it.
```json theme={null}
{
"external_ref": "odoo:4:partner:981",
"email": "customer@example.com",
"first_name": "Amina",
"last_name": "Khan"
}
```
Keep Odoo as the source of truth only for fields the business has deliberately
chosen to sync. Do not overwrite consent flags from a generic contact import.
## Order completion
On a paid or completed POS order, call `/marketplace/accrue`. Send:
* the mapped `card_id`;
* the Odoo partner external reference;
* the stable POS order reference;
* `amount_pence` when the card earns from spend; and
* the mapped Perkstar `locationId`.
Use Odoo's post-commit or job queue mechanism. If an Odoo transaction later
rolls back, it must not leave a loyalty award behind.
## Refunds and cancellations
On a confirmed refund, call `/marketplace/reverse` with the original external
transaction reference. Record the returned Perkstar reversal ID on the refund
record so support can trace both sides.
## Reconciliation job
Run a scheduled reconciliation that:
1. finds completed Odoo orders missing a Perkstar transaction ID;
2. retries them with the original idempotency and transaction references;
3. compares recent Perkstar transactions with Odoo orders; and
4. alerts on unmatched or terminal failures.
Webhooks make the integration responsive; reconciliation makes it reliable.
## Go-live sequence
1. Develop with a test key and existing Perkstar enrolment.
2. Verify test webhooks and duplicate delivery handling.
3. Test a timeout followed by a retry.
4. Test a full and partial Odoo refund policy with the business.
5. Create a new narrowly scoped live key.
6. Process one low-risk live order and confirm the wallet update.
7. Enable the connector location by location.
# Build a POS integration
Source: https://developers.perkstar.co.uk/guides/pos
Walk through a complete till journey: connect, identify, earn, display, reverse, and reconcile.
Start with [one tested stamp request and webhook receipt](/quickstart) before
building a complete POS adapter.
This walkthrough models the customer and cashier journey as well as the API
calls behind it. It uses the marketplace endpoints because one request can
resolve the customer, select the programme, find or create the enrolment, and
post loyalty safely.
Confirm the business and choose the exact card and location.
Scan or match the customer, then accrue loyalty with durable IDs.
Reverse refunds, retry timeouts, and reconcile missed events.
## Choose the installation model
Create a dedicated API key in that business's dashboard. This is the
simplest model for an in-house connector, one Odoo database, or one POS
merchant.
Grant `MARKETPLACE`, plus `LOCATIONS_READ` when the integration maps stores.
Add separate read scopes only for reconciliation jobs that need them.
Use OAuth when the same application will be installed by many businesses.
Each merchant consents to one organisation and your backend stores a
separate token set for it.
Follow the [OAuth marketplace guide](/guides/oauth-marketplace) before
implementing this walkthrough.
Start with a `pk_test_...` key. Test writes create isolated ledger rows but
do not alter live balances, wallet passes, or analytics. Test mode cannot
create live customers or enrolments, so prepare an existing enrolment first.
## The till journey
```mermaid theme={null}
sequenceDiagram
participant C as Customer wallet
participant T as Till / POS
participant P as Perkstar API
participant B as Partner backend
C->>T: Present wallet barcode
T->>B: Raw scanned value + basket reference
B->>P: POST /marketplace/accrue
P->>P: Resolve customer, card, enrolment
P->>P: Deduplicate external transaction
P-->>B: Customer + enrolment + transaction
B-->>T: Loyalty applied / reward state
P-->>C: Wallet pass refresh
Note over B,P: Webhooks + scheduled reconciliation keep both systems aligned
```
## Step 1: confirm the installation
```bash theme={null}
curl "$PERKSTAR_API_URL/marketplace/ping" \
--header "Authorization: Bearer $PERKSTAR_API_KEY"
```
Persist the returned organisation ID, currency, timezone, key mode, and card
choices. If `default_card_id` is `null`, the business has more than one active
card. Ask the operator to map each till programme or location to a specific
`card_id`; never select the first result silently.
A credential belongs to one Perkstar organisation. If the response names a
different business from the one your installation expects, stop setup rather
than writing to it.
## Step 2: map stores and programmes
Use `GET /locations` with `LOCATIONS_READ` to resolve Perkstar location IDs.
Store a mapping instead of comparing display names.
| POS concept | Perkstar value | Rule |
| - | - | - |
| Merchant/account | Organisation ID from `marketplace/ping` | Immutable installation owner |
| Loyalty programme | `card_id` | Explicit when several cards are active |
| Store/site | `location_id` | Map once, refresh when configuration changes |
| Order/payment | `external_transaction_id` | Stable and permanently unique for the business |
| Request attempt | `Idempotency-Key` | Reuse for every retry of the same operation |
## Step 3: identify the customer
Perkstar resolves identifiers in a fixed priority. Send only identifiers that
belong to the same person.
```json theme={null}
{
"identifier": {
"customer_id": "cus_123"
}
}
```
Map this opaque ID from an earlier Perkstar API or Zapier step. It is
scoped to the connected business. An unknown ID returns `404` and never
creates a replacement customer from the ID alone.
```json theme={null}
{
"identifier": {
"card_serial": "exact-value-returned-by-the-scanner"
}
}
```
Pass the scanned content unchanged. Current opaque POS identifiers and
older numeric/serial formats are supported. Do not parse, group, truncate,
convert case, or assume a fixed length.
```json theme={null}
{
"identifier": {
"external_ref": "odoo:company_4:partner_981"
}
}
```
Namespace stable IDs with the provider and account so two merchants cannot
accidentally generate the same local reference.
```json theme={null}
{
"identifier": {
"email": "alice@example.com"
}
}
```
Use contact details only when the POS has collected them legitimately. An
email match is case-insensitive; phone matching prefers normalised E.164
and retains the stored raw value as a compatibility fallback.
Resolution order is `customer_id`, `card_serial`, first-party provider
identity, `external_ref`, email, then phone. The first match wins.
## Step 4: add loyalty
```bash theme={null}
curl --request POST "$PERKSTAR_API_URL/marketplace/accrue" \
--header "Authorization: Bearer $PERKSTAR_API_KEY" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: odoo:company_4:order_94721:loyalty" \
--data '{
"identifier": { "card_serial": "value-from-scanner" },
"card_id": "card_123",
"transaction": {
"type": "STAMP",
"delta": 1,
"external_transaction_id": "odoo:company_4:order_94721",
"metadata": { "locationId": "location_123" }
}
}'
```
Send `type: "STAMP"` and the number of stamps in `delta`. Most integrations
send `1` after an eligible completed sale or visit.
Send the qualifying amount in `amount_pence`. Perkstar applies the card's
current points rule. Send an explicit `delta` only when the upstream system
is contractually authoritative for the points amount.
Use `ADJUST` only for an intentional correction with a useful note. A refund
should use reversal so the audit trail remains linked.
Two safety keys protect the operation:
* `Idempotency-Key` replays the same HTTP result during the request-cache
window; and
* `external_transaction_id` permanently prevents the same POS sale from
earning twice.
Use both and choose a namespace owned by your integration, such as
`odoo::order:`. Provider-managed prefixes such as `sq_payment_`
are reserved and return `400 reserved_external_transaction_id`. A timeout does
not prove the write failed.
## Step 5: update the till
Use the returned customer, enrolment, balance, and transaction to show a short,
stable result without making another request.
Loyalty was applied for the first time. Store the returned transaction ID
beside the POS order/payment reference.
The permanent external reference already existed. Treat this as a safe
replay, not a second award.
Test credentials cannot create a live customer or enrolment. Select an
existing testable customer and card, then retry.
The supplied identity or external transaction conflicts with an existing
record or environment. Stop and surface a staff-review state; do not invent
another identifier.
Honour `Retry-After` for `429`. Retry transient failures with backoff and
the same idempotency and external transaction IDs.
## Step 6: reverse a refund or void
```bash theme={null}
curl --request POST "$PERKSTAR_API_URL/marketplace/reverse" \
--header "Authorization: Bearer $PERKSTAR_API_KEY" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: odoo:company_4:refund_301" \
--data '{
"external_transaction_id": "odoo:company_4:order_94721",
"reason": "POS order refunded"
}'
```
Reversal writes a compensating transaction linked to the original. Replaying a
refund returns the existing reversal. Do not create an unrelated negative
award: it loses the original-sale link and weakens reconciliation.
## Step 7: work through outages
```mermaid theme={null}
flowchart TD
A["POS operation"] --> B{"Perkstar response received?"}
B -- Yes --> C{"Accepted or permanent error?"}
C -- Accepted --> D["Store Perkstar transaction ID"]
C -- Permanent error --> E["Show staff-review state"]
B -- No --> F["Queue locally with original IDs and occurred time"]
F --> G["Retry with backoff and the same IDs"]
G --> B
```
An offline queue should retain the original merchant, card, location, customer
identifier, transaction reference, idempotency key, amount, and occurrence
time. Encrypt local data, bound retention, and make failed entries visible to
staff.
## Step 8: reconcile
Webhooks provide fast updates; scheduled reads prove eventual consistency.
1. Subscribe to `transaction.created`, `customer.enrolled`,
`reward.redeemed`, and `tier.changed` as relevant.
2. Verify and persist each event before acknowledging it.
3. At least daily, compare recent POS references with Perkstar transactions.
4. Repair missing writes using the same stable IDs.
5. Alert on a queue that is old, repeatedly failing, or growing unexpectedly.
See the [webhook catalogue](/reference/webhook-events) for exact payloads.
## Go-live proof
* [ ] Installation identifies the expected organisation.
* [ ] Every store and loyalty programme is mapped explicitly.
* [ ] Old and current wallet barcode formats resolve unchanged.
* [ ] Replaying a sale never awards twice.
* [ ] A timeout followed by retry converges on one transaction.
* [ ] Full refund creates one linked reversal.
* [ ] Test traffic cannot change a live customer balance.
* [ ] Offline work survives restart and has a visible failure state.
* [ ] Webhook signatures and event deduplication are tested.
* [ ] Reconciliation finds and repairs a deliberately skipped event.
# Send push notifications
Source: https://developers.perkstar.co.uk/guides/wallet-pushes
Send a customer-safe wallet push or simulate delivery in test mode.
`POST /pushes` sends a push notification to the wallet pass attached to a
specific enrolment. The customer must have push marketing consent and an active
eligible card.
```bash theme={null}
curl --request POST "$PERKSTAR_API_URL/pushes" \
--header "Authorization: Bearer $PERKSTAR_API_KEY" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: summer-reminder-enrolment_123" \
--data '{
"enrollment_id": "enrolment_123",
"message": "Hi {firstName}, your {cardName} is ready for your next visit."
}'
```
## Merge fields
The message can use:
* `{firstName}`
* `{balance}`
* `{installLink}`
* `{shareLink}`
* `{cardName}`
* `{orgName}`
Keep the message useful without relying on a field that may be blank. Preview
the final wording in the dashboard before automating it.
## Delivery behaviour
* A three-minute cooldown applies per card across dashboard and API sends.
* `429` includes `Retry-After` when the cooldown or key limit is hit.
* The response reports attempted and failed platforms.
* Test credentials return `test_mode: true` without delivering or writing a broadcast row.
* A successful API response means Perkstar handed the update to the wallet platform; device display is controlled by Apple or Google.
Balance changes and reward events have their own service notifications and
wallet refresh pipeline. Use this endpoint for business-authored messages, not
as a replacement for posting the underlying loyalty transaction.
## Safe automation
* Send only when the workflow has a clear customer purpose.
* Respect consent and suppression state returned by Perkstar.
* Use one idempotency key per intended message.
* Do not include health data, payment details, passwords, or other sensitive information.
* Rate-limit upstream triggers so a bulk sync cannot notify the same customer repeatedly.
The public Perkstar app for Zapier exposes this operation as **Send Wallet
Push**. See the [Zapier catalogue](/integrations/zapier/triggers-actions) for its
mapping and [Zapier data and security](/integrations/zapier/data-security)
before sending a marketing message through a Zap.
# Receive webhooks
Source: https://developers.perkstar.co.uk/guides/webhooks
Verify signed Perkstar events, handle retries, and reconcile missed deliveries.
Webhooks notify your server when loyalty activity changes. Use them for fast
updates, then run periodic reconciliation so one delayed delivery cannot leave
systems permanently out of sync.
Building a Zap with the official Perkstar app? Follow [Connect Perkstar to
Zapier](/integrations/zapier/setup). Zapier creates, deletes, and recreates
its own event-specific subscriptions; you do not need to paste a Catch Hook
URL into Perkstar for the same trigger.
## Create an endpoint
Create webhook configuration with a narrowly scoped live key or in the
dashboard. The plaintext signing secret is returned once.
```bash theme={null}
curl --request POST "$PERKSTAR_API_URL/webhooks" \
--header "Authorization: Bearer $PERKSTAR_API_KEY" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: webhook-primary-v1" \
--data '{
"url": "https://integration.example.com/webhooks/perkstar",
"events": ["transaction.created", "customer.enrolled"],
"card_id": "card_123",
"mode": "live"
}'
```
Store the returned secret in the receiving service's secret manager before the
response is discarded.
Common event names include:
* `customer.enrolled`, `customer.unenrolled`, `customer.anonymized`,
`customer.group_changed`
* `wallet.installed`, `card.scanned`, `card.expired`, `referral.created`
* `transaction.created`, `reward.redeemed`, `coupon.redeemed`, `tier.changed`
* `membership.purchased`, `membership.renewed`, `membership.cancelled`
* `booking.created`, `booking.attended`, `booking.no_show`, `booking.cancelled`
* `webhook.test`
The [complete event catalogue](/reference/webhook-events) documents every
supported event, its exact `data` fields, and an example payload. Subscribe
only to events your receiver handles. An empty `events` array subscribes the
endpoint to all events. `card_id` is optional and excludes events for every
other card before delivery; events without a matching card are also excluded.
`mode` accepts `live`, `test`, or `all` and defaults to `all` for backward
compatibility. These filters avoid creating delivery rows or outbound requests
that the receiver would discard.
Some merchant events represent an observed state rather than a synchronous API
write. Recently issued Google Wallet passes are eligible for observation on a
15-minute schedule, but provider cadence, object age, and projector backlog
can extend the delay. Card scans cover successful online Perkstar Scanner
lookups only. Card expiry is per enrolment and effective expiry instant, and
lifecycle-group changes do not represent membership in saved segments. See
each event's boundary in the catalogue before designing a workflow.
When a business enables its first endpoint for `customer.group_changed` or
Google `wallet.installed`, allow one completed projection sweep for Perkstar
to store the current state without replaying historical customers or installs.
Tracking starts after that warm-up baseline. Apple installation is
callback-driven and does not use this warm-up.
## Event envelope
Every request body uses the same envelope:
```json theme={null}
{
"id": "whd_01JEXAMPLE",
"type": "transaction.created",
"created": 1785312000,
"orgId": "org_123",
"data": {
"transactionId": "txn_123",
"enrollmentId": "enr_123",
"type": "STAMP",
"delta": 1,
"occurredAt": "2026-07-30T10:00:00.000Z"
}
}
```
`id` is stable across automatic retries. For business events, `created` is the
source event's `data.occurredAt` time expressed as Unix seconds, so it also
remains stable. Deduplicate with `id`; do not use either timestamp as an
identity key.
Perkstar also sends:
| Header | Purpose |
| - | - |
| `X-Perkstar-Event` | Dotted event name |
| `X-Perkstar-Webhook-Id` | Configured endpoint ID |
| `X-Perkstar-Delivery-Id` | Stable logical delivery ID; matches body `id` |
| `X-Perkstar-Timestamp` | Unix time for this signing and delivery attempt |
| `X-Perkstar-Signature` | `t=...,v1=...` HMAC signature |
For a complete runnable test receiver, persistence example and expected-result
checklist, follow [Your first safe POS test](/quickstart#4-receive-a-signed-test-event).
## Verify before parsing
Perkstar sends a Stripe-style signature:
```http theme={null}
X-Perkstar-Signature: t=1785312000,v1=
```
The signed value is `.`. Verify the raw bytes and a
five-minute timestamp tolerance before trusting or parsing the JSON.
```ts theme={null}
import { verifyWebhookSignature } from "@perkstar/api-client/webhooks";
const rawBody = await request.text();
const event = verifyWebhookSignature({
payload: rawBody,
signature: request.headers.get("x-perkstar-signature") ?? "",
secret: process.env.PERKSTAR_WEBHOOK_SECRET!,
});
await processOnce(event.id, event);
return new Response(null, { status: 200 });
```
Reading JSON first and serialising it again changes the signed bytes. Capture
the raw body before any framework body parser runs.
## Processing rules
1. Verify the signature and timestamp.
2. Deduplicate by event ID in your database.
3. Persist or enqueue the event before returning `2xx`.
4. Process asynchronously when work could exceed a few seconds.
5. Make handlers safe when events arrive twice or out of order.
6. Branch test traffic using `testMode: true`.
Return a non-`2xx` status only when a retry may help. Validation failures should
be recorded for operator review rather than retried forever.
## Delivery schedule
Perkstar considers any `2xx` response successful. Network errors, timeouts, and
non-`2xx` responses are retried on this schedule:
| Attempt | Timing |
| - | - |
| 1 | Immediately |
| 2 | 1 minute after the first failure |
| 3 | 5 minutes after the second failure |
| 4 | 30 minutes after the third failure |
After four failed attempts, the delivery is marked exhausted and remains
available in the dashboard for inspection and manual resend. Keep each request
under ten seconds and acknowledge after durable persistence, before expensive
downstream work.
HTTP `410 Gone` is the exception to the retry schedule. Perkstar treats it as a
permanently removed callback, exhausts the current delivery immediately, and
pauses the endpoint so future events are not sent to a dead destination.
Automatic retries keep the same logical delivery `id`. A dashboard **Resend**
preserves that same logical ID. A receiver that has already committed the event
should acknowledge the duplicate without repeating its business action. If your
own downstream processing failed after receipt, retry it from your durable
inbox; a Perkstar resend must not bypass your deduplication protection.
## Test and operate the endpoint
In **Dashboard → Settings → Webhooks**, open the endpoint to:
* send a targeted `webhook.test` event while the endpoint is active;
* inspect attempt status, response code, duration, and the retained response
excerpt;
* resend a failed or exhausted delivery after fixing the receiver;
* pause the endpoint without deleting its configuration;
* rotate the signing secret and update the receiver immediately; or
* remove the endpoint and its delivery history.
Production endpoint URLs must use HTTPS and resolve only to public network
addresses. Perkstar blocks localhost, private/reserved IP ranges, and DNS
rebinding targets.
## Recent event feed
`GET /events` returns one canonical source event regardless of how many
endpoints received it. It requires the dedicated `EVENTS_READ` permission,
defaults to live records, supports dotted event, card, customer, time, and
live/test filters, and retains rows for 90 days. This permission is separate
from `WEBHOOKS_READ` so an existing key that can inspect endpoint configuration
does not automatically gain customer event payload access.
Use the feed for setup samples and bounded reconciliation. It is not a polling
replacement for an instant subscription and it does not reveal signing secrets
or internal event-deduplication keys.
## Reconciliation
At least daily, compare the external system with recent Perkstar transactions
or customers. Webhooks provide speed, while reconciliation catches exhausted
retries, downtime, and deployment mistakes.
# Perkstar developer platform
Source: https://developers.perkstar.co.uk/index
Connect POS, CRM, commerce, and back-office systems to Perkstar loyalty.
Build loyalty into the systems a business already uses. The Perkstar API lets an
integration find or create customers, enrol them onto cards, add stamps or
points, reverse mistakes, send wallet pushes, and receive signed webhooks.
Create a key, confirm the connection, and inspect your first response.
Scan a wallet pass, credit loyalty, and reverse a refunded sale safely.
Map customers and orders without duplicating records or rewards.
Use the generated reference, request builder, and response schemas.
Run every public operation with safe variables and built-in checks.
Install with OAuth, rotate tokens safely, and handle disconnects.
See available connections and follow merchant-friendly setup guides.
Use the public Perkstar app for 29 instant triggers, 10 scoped actions,
guided searches, and self-serve setup through OAuth.
Preview one dynamic instant trigger for 29 loyalty events, 11 guided
actions, two searches, and a universal API module in the private beta.
Use Perkstar's read-only MCP server with automatic OAuth discovery.
See live API, scanner, wallet, webhook, billing, and POS health.
Connect Resend for customer invitations and card-install links, with a
verified delivery test.
## Designed for production
* **Scoped access.** Each key can do only the jobs you select.
* **Safe retries.** Idempotency keys prevent a timeout from becoming a double stamp.
* **Permanent POS deduplication.** Stable transaction references remain unique beyond the 24-hour request cache.
* **Signed webhooks.** Verify every delivery before trusting its contents.
* **Request tracing.** Every response includes an `X-Request-Id` that Perkstar support can trace.
API access is available to eligible Perkstar plans. Create and manage keys in
**Dashboard → Settings → API keys**. A secret is shown once, so store it in a
server-side secret manager when it is created.
## Choose a starting point
| You are building | Start here |
| - | - |
| A POS or till plugin | [POS integration](/guides/pos) |
| An Odoo connector | [Odoo integration](/guides/odoo) |
| A CRM or customer import | [Customer sync](/guides/customer-sync) |
| A server that reacts to loyalty events | [Webhooks](/guides/webhooks) |
| A no-code workflow in Zapier | [Perkstar on Zapier](/integrations/zapier) |
| A visual scenario in Make | [Make private beta](/integrations/make) |
| A public marketplace application | [OAuth marketplace app](/guides/oauth-marketplace) |
| An AI assistant connection | [MCP server](/tools/mcp) |
| A TypeScript or Node.js service | [TypeScript SDK](/sdks/typescript) |
| A Python or Odoo service | [Python SDK](/sdks/python) |
# Access EPoS
Source: https://developers.perkstar.co.uk/integrations/access/index
Availability and next steps for Access EPoS.
**No self-service installation.** Reviewed 13 September 2026. The status shown
in the intended business's dashboard is authoritative for that account.
Connect Access hospitality locations when provider access and the production integration are released. This reference covers an existing or restricted connection. It is not an invitation to start a new connection.
## What to do now
Open **Perkstar → Integrations** and inspect Access EPoS. If it says **Coming soon**
or **Unavailable**, do not use an old setup URL or grant provider credentials to
work around it. Documentation and a provider's developer portal do not themselves
grant access to a Perkstar connector.
If you already have an approved connection, use **My integrations → Manage** where
available. Keep the original provider account and transaction references when
asking support about a failure. Do not disconnect a working installation merely
to test whether you can reconnect it.
## Discuss compatibility with support
Provide the business account number, provider product/version, country, relevant
store or location, and the loyalty workflow you need. Do not share passwords,
API keys or customer lists. Ask support to confirm both access and an appropriate
controlled test before relying on this connection for customer transactions.
For a bespoke connection, start with the [POS guide](/guides/pos) and
[API availability](/support/api-availability). A custom integration is a separate
implementation, not a way to enable an unreleased native connector.
# Acuity appointments and rewards
Source: https://developers.perkstar.co.uk/integrations/acuity/appointments-rewards
Understand customer matching, end-plus-15-minute attendance earning and one-time Acuity reward codes.
Acuity supplies the appointment lifecycle. Perkstar matches the booking to an
existing member, records attendance and controls the linked loyalty balance and
reward state.
## Match the existing member
Perkstar does not create customers or card enrolments from Acuity bookings.
Matching happens when attendance is due, in this order:
1. Find one active Perkstar customer by an exact, case-insensitive email match.
2. If email does not resolve one customer, normalise the Acuity phone number
using the business country and find one customer by phone.
3. Confirm that customer already has an active enrolment on the linked Stamp
card.
A name is stored only to help staff recognise the booking. It is never used to
match a customer. An ambiguous email or phone, an unmatched contact, or a
customer who has not joined the linked card does not earn.
Ask the customer to join the correct Perkstar card before the appointment. An
unmatched or not-enrolled attendance is not credited retrospectively, and
Perkstar does not turn the Acuity contact into a new loyalty member.
## Appointment updates and attendance
Perkstar maintains one signed `appointment.changed` subscription because
[Acuity defines it as the catch-all event](https://developers.acuityscheduling.com/docs/webhooks)
for scheduling, rescheduling, cancellation and detail changes. A daily
reconciliation reads the relevant appointment window again to close gaps after
a disabled webhook, provider error or deployment.
Confirmed appointments are auto-marked attended after the **scheduled end plus
15 minutes**. Perkstar uses a deterministic attendance reference, so webhook
retries, the daily reconciliation and repeated processing cannot credit the
same appointment twice.
## How earning is calculated
| Stamp card rule | Acuity attendance result |
| - | - |
| Visit-based | Awards the card's configured stamps per visit |
| Spend-based | Applies the card's spend threshold and stamps using the Acuity appointment price |
| Manual | Does not earn automatically because the booking has no staff-entered stamp amount |
Spend-based earning requires the same currency in Acuity and Perkstar and a
usable appointment price. A missing price does not invent a spend amount.
Acuity's `paid` indicator is recorded for context but is not an attendance
gate. A reserved or unpaid appointment can earn after attendance. Acuity
states that [payment-processor refunds are not reflected in
Acuity](https://help.acuityscheduling.com/hc/en-us/articles/28052155599885-Handling-refunds-and-price-adjustments),
so they are not synchronised into Perkstar; use an Acuity cancellation or
no-show when attendance should be corrected.
When Square routes earning to this same Stamp card, Square is the earning
owner, including while its connection temporarily needs reconnection. Acuity
still shows the appointment and can issue or reconcile reward codes, but it
skips attendance credit. Do not switch an established card's owner while
appointment or payment events may still be in flight.
## Issue a one-time reward code
Perkstar can provision codes for:
* the normal completed-card reward;
* a configured reward at a particular stamp milestone; and
* the card's birthday reward, when it issues a reward rather than extra stamps.
Perkstar confirms the reward is available on the linked card and selects the
Acuity coupon, package, gift or subscription source mapped to that reward.
The generated code is attached to that one Perkstar reward. Acuity applies
the source's service restrictions, value, usage and expiry.
Perkstar adds the code to the Wallet pass and sends the reward email when a
deliverable customer email is available. A configured booking button opens
Acuity with the code and customer booking details prefilled. On the default
Stamp card layout, an available issued code replaces the **Earned rewards**
count on the front with a **Code** field. The full reward list remains in
Pass Details. Redeeming the code restores the normal reward count; an
eligible cancellation makes the restored code visible again. Custom
front-field layouts remain unchanged.
The customer applies it in Acuity's package, gift or coupon field. Acuity
permits one coupon or package-style code per appointment.
When the appointment reports the managed code, Perkstar claims that exact
reward once, removes the code from Wallet and queues the Wallet update.
An unavailable or suppressed email does not make the reward disappear. Check
the customer's current Wallet pass. If the reward should also be emailed,
correct the customer email and follow the integration's retry guidance.
## What is retained
Perkstar retains the provider appointment reference, schedule and duration,
service and calendar/staff labels, appointment price and paid indicator,
cancellation or no-show state, customer contact fields needed for matching,
and whether a managed certificate was applied. Acuity intake-form answers,
internal notes, payment card details and payment-processor transactions are not
retained for this integration.
For corrections and delayed activity, continue to
[Cancellations and troubleshooting](/integrations/acuity/cancellations-troubleshooting).
# Acuity cancellations and troubleshooting
Source: https://developers.perkstar.co.uk/integrations/acuity/cancellations-troubleshooting
Correct cancellations and no-shows, diagnose missing attendance or reward codes and disconnect Acuity safely.
## Cancellations and no-shows
Record the real appointment outcome in Acuity. Perkstar reads the resulting
appointment state through the managed webhook or daily reconciliation and
applies the supported correction idempotently.
| Acuity outcome | Attendance credit | Managed reward code |
| - | - | - |
| Normal cancellation before attendance | No credit is added | A code applied to the booking is restored when still eligible |
| Normal cancellation after auto-attendance | The prior attendance credit is reversed | The applied code is restored when still eligible |
| No-show before attendance | No attendance credit is added | The code remains consumed |
| No-show after auto-attendance | The prior attendance credit is reversed | The code remains consumed |
A provider cancellation or no-show remains authoritative even if delivery is
late. Manual attendance corrections in Perkstar are limited to 72 hours.
If the earned value has already been used or later activity makes reversal
unsafe, Perkstar flags the booking for manual review instead of guessing.
Do not make a manual stamp or reward adjustment while an Acuity correction is
pending. The managed webhook or daily reconciliation may still apply the
automatic reversal or restoration, causing a duplicate correction.
An Acuity or payment-processor refund by itself does not change attendance or
reverse stamps. Acuity is the source of the appointment outcome, not payment
settlement.
## Troubleshooting
New connections require Perkstar Growth or higher and an active Acuity
account with the required API access. Sign in to Perkstar as an owner or
manager. The Acuity owner or a Scheduling Administrator should authorise the
connection so the OAuth user is not restricted to selected calendars.
Check the subscription for the exact Acuity account connected to Perkstar. A
saved Perkstar connection is not proof that its subscription or public
scheduler is active. If you have already paid, check the account and invoice
with Acuity support instead of purchasing again. Acuity documents Premium or
Powerhouse for API credentials; verify **View credentials** access if
Perkstar asks for a signing key. Once account access is working, complete a
real booking-to-reward test before inviting customers to use it.
In Acuity, open **Integrations → API → View credentials**. Copy the API key
belonging to the same Acuity user who authorised Perkstar. Perkstar verifies
the key and user ID with Acuity before saving it; a key from another user or
account cannot verify this connection.
Perkstar should maintain one `appointment.changed` subscription. Do not add
a manual Perkstar webhook. Reconnect or save the verified API key again so
Perkstar can inspect, remove stale managed subscriptions and restore the
catch-all subscription. The daily reconciliation remains the recovery path,
but the warning should still be resolved.
Confirm it belongs to the connected Acuity account and a calendar visible to
the user who authorised Perkstar. Check the integration account, timezone
and last sync. Allow the daily reconciliation to close a transient webhook
gap before recreating the appointment.
Wait until the scheduled end plus 15 minutes. Confirm the linked Stamp card
is active, the Acuity and Perkstar currencies match for spend earning, and
no Square route owns earning for the same card. The Acuity contact must
resolve uniquely by email or normalised phone to an existing Perkstar
customer who is already enrolled on that card. A name-only match, missing
enrolment or manual card rule does not earn. Interrupted loyalty writes are
durably retried by the attendance worker; do not manually add a duplicate
stamp while recovery is pending. A booking deliberately skipped because the
customer was not enrolled is not credited retroactively by a duplicate
delivery after they join.
Reconciliation splits full results by date and calendar and checks both
sorted ends of a dense day. If it still cannot prove that all appointments
were returned, it reports the affected window while continuing other
windows. Keep signed booking updates connected and contact support with the
affected dates and calendar numbers; do not treat that sync as complete.
Payment is not the attendance gate. A confirmed appointment can earn after
its end even when Acuity reports it unpaid. Acuity and processor refunds do
not sync into loyalty. Mark the appointment cancelled or no-show in Acuity
when the attendance outcome should reverse the credit.
Final reward appears for the Stamp card's completed-card reward. Milestone
and birthday rows appear only when those rewards exist on that same card.
Changing the attendance card disables codes and clears the previous
card-specific mappings.
Confirm online reward codes are enabled, the reward is mapped to a whole
numeric Acuity source ID and the source still exists. Save the mappings,
then use **Create existing codes** for eligible unclaimed rewards earned
before setup. A code can remain on Wallet even when email delivery is
unavailable or suppressed.
Check the source's expiry, remaining use, eligible appointment types and
value in Acuity. Only one coupon, package, gift or subscription code can be
applied to an appointment. Do not replace the Perkstar-generated code with a
reusable public coupon.
Perkstar pauses automatic work rather than choosing an account. Contact
[Perkstar support](mailto:support@perkstar.co.uk) to separate the
connections safely.
## Disconnect safely
Disconnect in Perkstar **before** revoking Perkstar from Acuity. Working
Acuity access is required to remove managed certificates and the webhook
subscription safely.
Allow any displayed cancellation, no-show or certificate cleanup to finish
and record the affected appointment numbers.
Open **Settings → Integrations → Acuity** and choose **Disconnect Acuity**.
Perkstar first retires managed Acuity certificates and removes its managed
webhook subscription.
Keep Acuity authorised. If Perkstar reports pending certificate or webhook
cleanup, wait briefly and choose disconnect again rather than revoking the
account first.
Only after Perkstar reports the integration disconnected should you remove
its access from Acuity.
Disconnecting stops appointment sync and new automatic reward codes. Open
bookings are unlinked from the attendance card, and managed codes are removed
from Wallet as cleanup completes. Existing Perkstar customers, card
enrolments, cards, completed booking records, transaction history and earned
loyalty rewards remain under the normal retention rules.
Already revoked Acuity access first? Do not make replacement loyalty
adjustments. Email [support@perkstar.co.uk](mailto:support@perkstar.co.uk) with
the Perkstar business name and affected appointment numbers so cleanup can be
reviewed without exposing customer contact details or credentials.
# Acuity Scheduling
Source: https://developers.perkstar.co.uk/integrations/acuity/index
Connect Acuity appointments to an existing Perkstar Stamp card for attendance earning and one-time online reward codes.
Use Acuity Scheduling as the appointment system while Perkstar remains the
loyalty system of record. Appointments sync into **Bookings**, eligible
attendance credits an existing Stamp card enrolment, and configured rewards
receive a one-time Acuity code for online booking.
Match one existing Perkstar customer and card enrolment by email or
normalised phone number. Names are never used for matching.
Mark a confirmed appointment attended after its end time plus 15 minutes and
apply the linked card's visit or spend rule once.
Create a unique Acuity certificate for a completed-card, milestone or
birthday reward and keep the code on the customer's Wallet pass.
## System boundaries
| Event or responsibility | System of record | Result |
| - | - | - |
| Appointment schedule, service, calendar and status | Acuity | Perkstar keeps the fields required to show and reconcile the booking |
| Loyalty membership, stamps, rewards and Wallet pass | Perkstar | An eligible attended appointment credits the existing enrolment once |
| Coupon, package, gift or subscription value and restrictions | Acuity | Perkstar creates a unique code against the configured Acuity source |
| Appointment payment and payment-processor refund | Acuity or its payment processor | Perkstar does not use payment status as an attendance gate and does not sync refunds |
| Normal cancellation or no-show | Acuity | Perkstar applies the supported loyalty and certificate correction once |
Acuity is an **attendance integration, not a payment-settlement integration**.
A paid flag is not required for attendance earning, and an Acuity or
payment-processor refund does not reverse loyalty. Record a normal
cancellation or no-show in Acuity when the appointment outcome changes.
## Important boundaries
* Acuity supports **Stamp cards only**. Points, Cashback and other card types
are not available for this connection.
* One Acuity account and one Stamp card can be linked to a Perkstar business.
The same route applies across that Acuity account's calendars, staff and
appointment types.
* The customer must already exist in Perkstar and already be enrolled on the
linked card. Acuity bookings never create a customer or a card enrolment.
* Matching uses a unique case-insensitive email first, then a normalised phone
number. A name alone never matches.
* Visit rules use the configured stamps per visit. Spend rules use the Acuity
appointment price and require matching Acuity and Perkstar currencies.
Manual earning rules do not award automatically.
If the same Stamp card is routed to Square, **Square owns earning**, including
while that connection temporarily needs reconnection. Acuity continues to sync
appointments and provide configured reward codes, but does not add a second
credit. Keep that ownership stable while appointment or payment events may
still be in flight; use a new card or contact support for a clean cutover.
## What you need
* A Perkstar **Growth** plan or higher.
* An active Acuity account with the required API access. Acuity documents
**Premium or Powerhouse** for API credentials; check the authorising user's
access before changing plans, as explained in [Setup](/integrations/acuity/setup).
* Perkstar owner or manager access with permission to edit operations.
* The Acuity account owner or a **Scheduling Administrator** to authorise the
connection. Lower contributor levels can be limited to selected calendars.
* One unarchived active or draft Stamp card. A draft can award stamps during a
controlled test; activate it before serving customers.
* Existing Perkstar customers already enrolled on that card.
* The same business currency in Acuity and Perkstar if the card earns by spend.
**Earning stamps only?** No Acuity coupon is needed. **Redeeming rewards
during online booking?** First create the matching coupon or package in
Acuity, including its value, eligible services and intended single-use limit,
then link its numeric ID in Perkstar. Perkstar automatically creates each
earned reward's unique customer code; it does not create the underlying
discount or offer for you.
Authorise the complete account, verify booking updates, link the card and
test the full journey.
Understand matching, attendance earning and the customer reward-code flow.
Correct cancellations and no-shows, diagnose missing activity and disconnect
safely.
## Data flow
| Direction | Information | Purpose |
| - | - | - |
| Acuity → Perkstar | Account identity and currency; appointment reference, times, duration, service, calendar/staff label, price, paid indicator, cancellation/no-show state, customer name, email and phone, and whether a certificate was applied | Display and reconcile the booking, match an existing customer, calculate attendance earning and detect a managed code |
| Perkstar → Acuity | One managed `appointment.changed` webhook subscription; generated certificate code, configured source ID and customer email where available | Receive appointment changes and create the customer's one-time reward code |
| Perkstar → customer | Reward email where deliverable, booking link and updated Apple Wallet or Google Wallet pass | Let the customer use and track the reward |
Perkstar retains only the appointment fields required for this workflow. It
does not retain Acuity intake-form answers, internal appointment notes, payment
card details or payment-processor transactions.
Need help with a connection? Email
[support@perkstar.co.uk](mailto:support@perkstar.co.uk) with the Perkstar
business name, Acuity appointment number and approximate time. Never send an
API key, access token, customer intake-form answer or full webhook payload.
# Set up Acuity
Source: https://developers.perkstar.co.uk/integrations/acuity/setup
Authorise the complete Acuity account, verify booking updates, link an existing Stamp card and test attendance and reward codes.
Complete these steps before relying on automatic attendance earning. Perkstar
keeps appointment sync, attendance earning and online reward codes as separate
setup stages so each can be verified safely.
## Before you connect
* Use Perkstar Growth or higher.
* Use an active Acuity account. Acuity documents that
[its API access requirements](https://help.acuityscheduling.com/hc/en-us/articles/16676949253389-Using-custom-CSS-and-APIs).
Its **Premium or Powerhouse** plans include access to API credentials. If
Perkstar asks for your webhook signing key, confirm that **View credentials**
is available for the authorising user before changing any subscription.
OAuth authorisation and access to that credentials screen are separate checks;
a Connect button alone does not confirm either one.
* Sign in to Perkstar as an owner or manager who can edit operations.
* Ask the Acuity owner or a **Scheduling Administrator** to authorise Perkstar.
Acuity's lower contributor levels can be limited to selected calendars; see
[Acuity access levels](https://help.acuityscheduling.com/hc/en-us/articles/16676924963341-Inviting-contributors-to-Acuity-Scheduling).
* Confirm that you are connecting the intended Acuity account. Perkstar
supports one Acuity account per business.
### Direct links to Acuity
Sign in to **your own Acuity account** and check the business before making
changes. These links contain no account, owner or coupon ID;
Acuity opens them using your own login. Keep Perkstar open in another browser
tab so you can return to finish setup. If Acuity asks you to sign in first,
finish signing in and open the required link again.
* [Create an appointment coupon](https://secure.acuityscheduling.com/products.php?action=editCoupon\&apptCoupon=1)
* [Open your appointment coupons](https://secure.acuityscheduling.com/products.php?action=coupons\&apptCoupon=1)
* [Open Acuity Integrations / API](https://secure.acuityscheduling.com/preferences.php?action=integrations)
* [Acuity's illustrated coupon help](https://help.acuityscheduling.com/hc/en-us/articles/16676933307789-Creating-coupons-for-appointments-and-packages-in-Acuity-Scheduling)
— public help, with no Acuity account login required.
## Prepare the Stamp card
The card picker shows unarchived **active or draft Stamp cards**. Points,
Cashback and other card types are not eligible.
Before going live, confirm that:
* test earning on a draft if useful, then activate the card before serving
customers;
* the customers you want to reward already exist in Perkstar and are already
enrolled on this card;
* an automatic visit or spend rule is configured;
* Acuity and Perkstar use the same currency if the card earns by spend; and
* the expected final, milestone and birthday rewards exist on the card.
A manual earning rule does not credit appointments automatically. Perkstar
cannot infer how many stamps a staff member intended to enter.
Check whether this card is also routed to Square. If it is, Square remains the
earning owner, including while its connection temporarily needs reconnection,
and Acuity will not award attendance a second time. Keep the owner stable
while appointment or payment events may still be in flight. Use a new card or
contact support before switching an established card between providers.
## Connect and verify booking updates
In Perkstar, open **Integrations → Marketplace**. On a phone, use Safari or
Chrome, tap the menu button at the top right, then **Integrations →
Marketplace**. Use the browser, not the Acuity admin app, for this setup.
Find **Acuity Scheduling** and choose **Connect** on Overview or Setup. This
opens the guided management page; choose **Continue to Acuity** to
authorise. Before the first connection, Setup should show **Not started**.
You do not need to register a developer application or ask Perkstar support
to perform the normal connection.
Sign in to the correct Acuity account as its owner or Scheduling
Administrator and approve Perkstar's API access. On return, check the
displayed Acuity account, timezone and currency.
Acuity signs a dynamic webhook with the API key belonging to the user who
authorised it. In Acuity, open **Integrations**, scroll to **API**, choose
**View credentials**, and copy the API key for that same user. Paste it in
Perkstar. Perkstar verifies the user ID and key with Acuity before saving it
securely.
Perkstar automatically maintains one catch-all `appointment.changed`
webhook. Do not add a Perkstar webhook manually in Acuity. The integration
should report that booking updates are connected.
Select the prepared card under **Choose the programme credited after
attendance** (called **Link your stamp card** in the older settings view).
The selection saves automatically and is applied to open, uncredited Acuity
bookings where safe.
Connecting authorises account access; it does not by itself turn on attendance
earning. Complete **Booking updates** and **Loyalty programme**, then run a test.
The third stage, **Reward codes**, is **required for redemption during Acuity
booking** and is counted separately from attendance earning. Skip it only if
rewards will be redeemed in person. A cancelled or failed authorisation shows a message on the
management page explaining how to continue.
Changing the linked Stamp card turns Acuity reward codes off and clears the
previous card's reward-source mappings. Reconfigure the online rewards step
before issuing codes from the new card.
## Configure online reward codes
**Complete this stage if customers should use rewards at Acuity checkout.**
Customers can still earn attendance stamps with online reward codes off, but
must redeem those rewards in person instead.
You create the coupon or package that defines the reward in Acuity first.
Perkstar does **not** create that discount or decide its value and eligible
services for you. After you link it below, Perkstar automatically creates each
customer's unique code when they earn the mapped reward. You do not need to
create a separate coupon manually for every customer.
For an appointment discount or free service, open **Appointment Types →
Coupons → New Coupon for Appointments** in Acuity. Choose the discount,
eligible appointment types and expiry. For a single-use reward, set the
**Total number of uses...** to **1 total use**, not unlimited or once per
client email.
Keep the original setup code private; customers receive their own codes
from Perkstar. You can do this in a mobile browser or Acuity's admin app.
Alternatively, create an appointment package, gift or subscription with the
intended reward entitlement. Use separate sources when completed-card,
milestone or birthday rewards have different terms. Test the generated
code's actual usage limits in Acuity. A
unique generated code does not by itself make an unlimited-use source
single-use.
Under **Let customers use rewards when booking**, enable **Online Acuity
reward codes** and add the business's HTTPS Acuity booking page.
For every reward you want available online, choose **Coupon or discount** or
**Package, gift or subscription**, then enter its numeric Acuity reward
number from its edit page in **Acuity ID**, not the text of a discount code.
For a coupon, copy the digits after `id=` in its browser address. On a
phone, tap the address bar to see the full address.
Leave a row blank
when that reward should remain in-person only.
Choose **Save reward setup**. If customers already have eligible unclaimed
rewards, use **Create waiting codes** after the mappings are saved.
The customer-facing label is **Acuity coupon code**. This is different from
the numeric **Acuity ID** you copied from the coupon edit-page URL during setup.
Customers enter their Acuity coupon code in **Package, gift, or coupon code** at
Acuity checkout. Test an earned code against the intended service before going
live; check its discount and that it cannot be used a second time. Percentage
coupons can include add-ons, and a required deposit may still be payable, so
confirm the booking total rather than assuming every free-service reward makes
every booking free.
### What can be automated?
Perkstar already automates the repeated work: creating an individual Acuity code
when a mapped reward is earned and keeping the reward's redemption status in
sync. The business creates and links the underlying offer once per reward type.
Acuity's documented [certificate creation API](https://developers.acuityscheduling.com/reference/post-certificates)
requires an existing coupon or package ID. Its public API documentation does
not provide an endpoint for creating the underlying discount or package. The
standard Perkstar connection therefore does not create those offers for you.
Acuity explains how to [create appointment coupons](https://help.acuityscheduling.com/hc/en-us/articles/16676933307789-Creating-coupons-for-appointments-and-packages-in-Acuity-Scheduling)
and how customers [use package, gift and subscription codes](https://help.acuityscheduling.com/hc/en-us/articles/29268134579085-Redeeming-package-gift-certificate-or-subscription-codes).
## Customer information
Perkstar reads only the account and appointment fields required to display and
reconcile bookings, match an existing customer and operate a reward code. It
does not retain intake-form answers or internal appointment notes. When a
reward code is created, Perkstar sends Acuity the configured source, generated
code and the customer's email where available. A configured booking link can
prefill the code and the customer's booking details.
The business must tell customers about this provider connection and have an
appropriate lawful basis for the data exchange.
* [Perkstar privacy policy](https://dashboard.perkstar.co.uk/privacy)
* [Integration recipients](https://dashboard.perkstar.co.uk/dpa/sub-processors)
## Test before going live
Use a synthetic customer who already exists in Perkstar and is enrolled on the
linked active Stamp card.
1. Book an Acuity appointment using the same email address and confirm it
appears in Perkstar **Bookings**.
2. Reschedule it and confirm its service time changes without creating a
duplicate booking.
3. Let a short appointment reach its end time, wait at least 15 minutes and
confirm the exact visit- or spend-based stamp credit appears once.
4. Repeat with phone matching in a different display format and confirm the
normalised number resolves the same enrolled customer.
5. Confirm that a name-only, unmatched or not-enrolled booking does not earn
and does not create a customer or enrolment.
6. Earn one configured reward and confirm the email where deliverable, Wallet
reward and one-time Acuity code.
7. Book with the code and confirm Perkstar records one redemption and removes
the used code from Wallet.
8. Cancel one code booking normally and confirm the reward is restored. Mark a
separate code booking as a no-show and confirm its code remains consumed.
Continue with [Appointments and rewards](/integrations/acuity/appointments-rewards).
# Aloha Cloud (NCR Silver)
Source: https://developers.perkstar.co.uk/integrations/aloha-cloud/index
Availability and next steps for Aloha Cloud (NCR Silver).
**Not open for new connections.** Reviewed 13 September 2026. The status shown
in the intended business's dashboard is authoritative for that account.
Configure per-location Aloha Cloud access for sales polling and card routing when released. The current workspace does not offer general self-service setup for this provider.
## What to do now
Open **Perkstar → Integrations** and inspect Aloha Cloud (NCR Silver). If it says **Coming soon**
or **Unavailable**, do not use an old setup URL or grant provider credentials to
work around it. Documentation and a provider's developer portal do not themselves
grant access to a Perkstar connector.
If you already have an approved connection, use **My integrations → Manage** where
available. Keep the original provider account and transaction references when
asking support about a failure. Do not disconnect a working installation merely
to test whether you can reconnect it.
## Discuss compatibility with support
Provide the business account number, provider product/version, country, relevant
store or location, and the loyalty workflow you need. Do not share passwords,
API keys or customer lists. Ask support to confirm both access and an appropriate
controlled test before relying on this connection for customer transactions.
For a bespoke connection, start with the [POS guide](/guides/pos) and
[API availability](/support/api-availability). A custom integration is a separate
implementation, not a way to enable an unreleased native connector.
# Clover
Source: https://developers.perkstar.co.uk/integrations/clover/index
Availability and next steps for Clover.
**Controlled rollout.** Reviewed 13 September 2026. The status shown in the
intended business's dashboard is authoritative for that account.
Use the Clover app for scan-first customer identification, loyalty earning, redemption and refund recovery. Access requires explicit release approval and the required provider configuration; an eligible subscription alone does not enable it.
## What to do now
Open **Perkstar → Integrations** and inspect Clover. If it says **Coming soon**
or **Unavailable**, do not use an old setup URL or grant provider credentials to
work around it. Documentation and a provider's developer portal do not themselves
grant access to a Perkstar connector.
If you already have an approved connection, use **My integrations → Manage** where
available. Keep the original provider account and transaction references when
asking support about a failure. Do not disconnect a working installation merely
to test whether you can reconnect it.
## Discuss compatibility with support
Provide the business account number, provider product/version, country, relevant
store or location, and the loyalty workflow you need. Do not share passwords,
API keys or customer lists. Ask support to confirm both access and an appropriate
controlled test before relying on this connection for customer transactions.
For a bespoke connection, start with the [POS guide](/guides/pos) and
[API availability](/support/api-availability). A custom integration is a separate
implementation, not a way to enable an unreleased native connector.
# Connect and verify safely
Source: https://developers.perkstar.co.uk/integrations/connection-checklist
A short checklist for account ownership, access, the first result and recovery.
## Before connecting
1. Confirm the business account and the provider account or store. Give the connection
a recognisable name where supported.
2. Read the integration's availability and requirements. A provider account and a
paid Perkstar plan do not automatically grant every connector.
3. Decide who owns the connection and who will respond when it needs attention.
4. Review the requested access and keep keys and verification tokens private.
## Verify one result
Use an authorised fixture or controlled test appropriate to the integration.
| Connection | First useful result |
| - | - |
| Resend | Its signed test-delivery confirmation, followed by explicit activation |
| POS or online store | One eligible sale matched to the intended customer, card and location |
| Bookings | One qualifying attended appointment and the corresponding loyalty action |
| Klaviyo | The expected profile and event, without accidentally starting a live email flow |
| Analytics | A supported event in the correct property with required consent |
| Zapier or Make | One workflow execution with the expected output in the destination |
| Stripe Connect | Required onboarding completed and the correct charge/payout readiness |
A connected badge proves authorisation or configuration, not that every business
event succeeded. Read the reason, timestamp and relevant provider record behind a
status. A missing signal is not a healthy signal.
## Duplicates and recovery
For custom API writes, keep a stable source reference and follow
[idempotency](/fundamentals/idempotency). Repeat the same controlled request and
verify that it does not duplicate loyalty. Follow the provider-specific guide for
refunds, cancellations and recovery. Do not run a bulk retry because a summary
looks stale; first establish which records were accepted or completed.
For webhooks, use the [receiver walkthrough](/guides/webhooks). Check the signed
payload and delivery status. A redirect is not a successful receiver response.
## Hand over ownership
Record the responsible business user, provider account, programme/location mapping,
last verified result and recovery instructions. Store secrets in the appropriate
secure system rather than in this handover. Before revoking access or disconnecting,
review pending work and how late delivery reports will be reconciled.
# Deliveroo
Source: https://developers.perkstar.co.uk/integrations/deliveroo/index
Availability and next steps for Deliveroo.
**No self-service installation.** Reviewed 13 September 2026. The status shown
in the intended business's dashboard is authoritative for that account.
Route completed Deliveroo orders to loyalty cards using the restaurant mapping managed in Perkstar. This reference covers an existing or restricted connection. It is not an invitation to start a new connection.
## What to do now
Open **Perkstar → Integrations** and inspect Deliveroo. If it says **Coming soon**
or **Unavailable**, do not use an old setup URL or grant provider credentials to
work around it. Documentation and a provider's developer portal do not themselves
grant access to a Perkstar connector.
If you already have an approved connection, use **My integrations → Manage** where
available. Keep the original provider account and transaction references when
asking support about a failure. Do not disconnect a working installation merely
to test whether you can reconnect it.
## Discuss compatibility with support
Provide the business account number, provider product/version, country, relevant
store or location, and the loyalty workflow you need. Do not share passwords,
API keys or customer lists. Ask support to confirm both access and an appropriate
controlled test before relying on this connection for customer transactions.
For a bespoke connection, start with the [POS guide](/guides/pos) and
[API availability](/support/api-availability). A custom integration is a separate
implementation, not a way to enable an unreleased native connector.
# Dojo
Source: https://developers.perkstar.co.uk/integrations/dojo/index
Availability and next steps for Dojo.
**Not open for new connections.** Reviewed 13 September 2026. The status shown
in the intended business's dashboard is authoritative for that account.
Turn verified Dojo payment events into loyalty activity with customer matching and refund handling. The current workspace does not offer general self-service setup for this provider.
## What to do now
Open **Perkstar → Integrations** and inspect Dojo. If it says **Coming soon**
or **Unavailable**, do not use an old setup URL or grant provider credentials to
work around it. Documentation and a provider's developer portal do not themselves
grant access to a Perkstar connector.
If you already have an approved connection, use **My integrations → Manage** where
available. Keep the original provider account and transaction references when
asking support about a failure. Do not disconnect a working installation merely
to test whether you can reconnect it.
## Discuss compatibility with support
Provide the business account number, provider product/version, country, relevant
store or location, and the loyalty workflow you need. Do not share passwords,
API keys or customer lists. Ask support to confirm both access and an appropriate
controlled test before relying on this connection for customer transactions.
For a bespoke connection, start with the [POS guide](/guides/pos) and
[API availability](/support/api-availability). A custom integration is a separate
implementation, not a way to enable an unreleased native connector.
# EPOS Now
Source: https://developers.perkstar.co.uk/integrations/epos-now/index
Availability and next steps for EPOS Now.
**Not open for new connections.** Reviewed 13 September 2026. The status shown
in the intended business's dashboard is authoritative for that account.
Configure EPOS Now credentials for sales polling and customer matching when the connector is released. The current workspace does not offer general self-service setup for this provider.
## What to do now
Open **Perkstar → Integrations** and inspect EPOS Now. If it says **Coming soon**
or **Unavailable**, do not use an old setup URL or grant provider credentials to
work around it. Documentation and a provider's developer portal do not themselves
grant access to a Perkstar connector.
If you already have an approved connection, use **My integrations → Manage** where
available. Keep the original provider account and transaction references when
asking support about a failure. Do not disconnect a working installation merely
to test whether you can reconnect it.
## Discuss compatibility with support
Provide the business account number, provider product/version, country, relevant
store or location, and the loyalty workflow you need. Do not share passwords,
API keys or customer lists. Ask support to confirm both access and an appropriate
controlled test before relying on this connection for customer transactions.
For a bespoke connection, start with the [POS guide](/guides/pos) and
[API availability](/support/api-availability). A custom integration is a separate
implementation, not a way to enable an unreleased native connector.
# Google Analytics 4
Source: https://developers.perkstar.co.uk/integrations/ga4/index
Configure Google Analytics 4 measurement for supported customer journeys.
Send supported customer journey events to your business's Google Analytics 4 account. This
is measurement, not a loyalty balance source or proof that a message was delivered.
## Configure the connection
1. Select the intended business in **Perkstar → Integrations → Google Analytics 4 → Connect**.
2. Enter the **Measurement ID** and **Measurement API secret** from the property or data source you
control in Google Analytics.
3. Save in the integration workspace. These are business-level settings inherited
by its cards; do not paste a different business's credentials into a card.
4. A saved-secret hint means the secret is already stored. Leaving it untouched
preserves it; entering a replacement deliberately updates it.
## Check an event
Use a controlled test customer and a supported enrolment or loyalty journey with
the required recorded marketing consent. Inspect the matching event in Google Analytics.
The implementation requires both the identifier and secret, plus the applicable
consent, before firing these events. A saved identifier alone is not a completed
verification.
## Troubleshooting and ownership
Check the correct business, identifier, saved secret and test customer's consent.
Provider reporting can differ from Perkstar transaction totals; attribution events
are not the accounting record. Do not remove consent requirements to make a test
appear. Keep secrets private and rotate them through the provider when necessary.
Use the available workspace controls to remove the configuration when retiring it,
then confirm with a controlled test that no new event is generated.
See [security and privacy](/fundamentals/security-privacy).
# Google Calendar
Source: https://developers.perkstar.co.uk/integrations/google-cal/index
Availability and next steps for Google Calendar.
**Not open for new connections.** Reviewed 13 September 2026. The status shown
in the intended business's dashboard is authoritative for that account.
Bring calendar appointments into the loyalty workflow when the connector is released. The current workspace does not offer general self-service setup for this provider.
## What to do now
Open **Perkstar → Integrations** and inspect Google Calendar. If it says **Coming soon**
or **Unavailable**, do not use an old setup URL or grant provider credentials to
work around it. Documentation and a provider's developer portal do not themselves
grant access to a Perkstar connector.
If you already have an approved connection, use **My integrations → Manage** where
available. Keep the original provider account and transaction references when
asking support about a failure. Do not disconnect a working installation merely
to test whether you can reconnect it.
## Discuss compatibility with support
Provide the business account number, provider product/version, country, relevant
store or location, and the loyalty workflow you need. Do not share passwords,
API keys or customer lists. Ask support to confirm both access and an appropriate
controlled test before relying on this connection for customer transactions.
For a bespoke connection, start with the [POS guide](/guides/pos) and
[API availability](/support/api-availability). A custom integration is a separate
implementation, not a way to enable an unreleased native connector.
# Find your integration
Source: https://developers.perkstar.co.uk/integrations/index
Choose a connection, check availability and follow the correct setup guide.
Connect an existing business tool, send customer invitations from your own email
account, or build with the API. Start with the job you need to do.
Connect, test and activate your own sending account.
Confirm access, ownership, one result and recovery.
Start with a scoped test key and a small request.
## Find your provider
**Available** means a connection is offered subject to the business's permissions,
plan and provider configuration. **Beta / controlled rollout** may require explicit
access. A listing here does not enable a provider that the dashboard marks unavailable.
Availability reviewed **13 September 2026**.
### Email and marketing
| Integration | Availability | What the guide helps with |
| - | - | - |
| [Resend](/integrations/resend) | Available | Send invitations and card install links through your own email account. |
| [Klaviyo](/integrations/klaviyo) | Available | Sync customer profiles, loyalty properties and lifecycle events into Klaviyo segments and flows. |
| [Mailchimp](/integrations/mailchimp) | Beta | Sync consenting loyalty customers and their current balances, tiers, birthdays and activity into a Mailchimp audience. |
### Point of sale
| Integration | Availability | What the guide helps with |
| - | - | - |
| [Loyverse](/integrations/loyverse) | Beta | Scan Wallet QR codes, earn points from paid receipts and spend a Perkstar points-to-cash balance at the till. |
| [Square](/integrations/square) | Beta / controlled rollout | Earn loyalty from customer-attributed Square payments with refund reconciliation and location routing. |
| [SumUp POS (Custom Loyalty)](/integrations/sumup-pos) | Beta / controlled rollout | Use SumUp POS Custom Loyalty for Wallet QR lookup, loyalty rewards and replay-safe completed-sale settlement. |
| [Clover](/integrations/clover) | Beta / controlled rollout | Use the Clover app for scan-first customer identification, loyalty earning, redemption and refund recovery. |
| [Lightspeed Restaurant K-Series](/integrations/lightspeed-k-series) | Beta / controlled rollout | Reconcile eligible closed restaurant sales and refunds for existing Perkstar members. |
| [Lightspeed Retail](/integrations/lightspeed) | Not open for new connections | Connect Lightspeed Retail sales and customer activity when the integration is released. |
| [Aloha Cloud (NCR Silver)](/integrations/aloha-cloud) | Not open for new connections | Configure per-location Aloha Cloud access for sales polling and card routing when released. |
| [EPOS Now](/integrations/epos-now) | Not open for new connections | Configure EPOS Now credentials for sales polling and customer matching when the connector is released. |
| [GoDaddy Poynt](/integrations/poynt) | Not open for new connections | Configure a Poynt business for sales polling and customer matching when released. |
| [MX POS](/integrations/mx-pos) | Not open for new connections | Configure MX POS transaction polling and card routing when the connector is released. |
| [Dojo](/integrations/dojo) | Not open for new connections | Turn verified Dojo payment events into loyalty activity with customer matching and refund handling. |
| [Toast](/integrations/toast) | Existing / restricted connections | Connect Toast sales and customer activity when the production integration is released. |
| [Access EPoS](/integrations/access) | Existing / restricted connections | Connect Access hospitality locations when provider access and the production integration are released. |
| [Sunmi](/integrations/sunmi) | Existing / restricted connections | Connect Sunmi Cloud locations for sales polling when the production connector is released. |
| [PAX](/integrations/pax) | Unavailable | PAXSTORE manages terminal fleets but does not provide the transaction feed Perkstar requires. |
Square credits customer-attributed sales and reverses refunds.
Unmatched Square contacts are not retained.
Rewards redeem through the Perkstar pass and scanner;
Square Loyalty is not required or written. See the [Square guide](/integrations/square)
for the production beta’s access and data-use requirements.
### Online stores and payments
| Integration | Availability | What the guide helps with |
| - | - | - |
| [Shopify](/integrations/shopify) | Beta | Reward online and POS orders with customer matching, refund recovery, catalogue sync and location routing. |
| [Stripe Connect](/integrations/stripe) | Available | Connect Stripe to receive customer payments and manage payout readiness from Perkstar. |
### Bookings and delivery
| Integration | Availability | What the guide helps with |
| - | - | - |
| [Acuity Scheduling](/integrations/acuity) | Available | Reward attended appointments, handle no-shows safely and configure booking redemption codes. |
| [Google Calendar](/integrations/google-cal) | Not open for new connections | Bring calendar appointments into the loyalty workflow when the connector is released. |
| [Setmore](/integrations/setmore) | Not open for new connections | Sync appointments and credit the customer's wallet after attendance. |
| [Mindbody](/integrations/mindbody) | Not open for new connections | Connect a studio to reward eligible class and appointment attendance. |
| [Deliveroo](/integrations/deliveroo) | Existing / restricted connections | Route completed Deliveroo orders to loyalty cards using the restaurant mapping managed in Perkstar. |
### Analytics
| Integration | Availability | What the guide helps with |
| - | - | - |
| [Google Analytics 4](/integrations/ga4) | Available | Send supported customer journey events to the business's GA4 property. |
| [Meta Pixel](/integrations/meta-pixel) | Available | Measure supported sign-up and loyalty activity in Meta without exposing customer secrets. |
| [TikTok Pixel](/integrations/tiktok-pixel) | Available | Measure supported sign-up and loyalty activity in TikTok Ads Manager. |
### Automation
| Integration | Availability | What the guide helps with |
| - | - | - |
| [Zapier](/integrations/zapier) | Public beta | Use Perkstar triggers and actions in Zapier to connect loyalty activity with other business tools. |
| [Make](/integrations/make) | Private beta | Build visual loyalty automations with Make modules and webhooks when the public connector is released. |
## Build without a native connector
Use the [POS walkthrough](/guides/pos), [customer sync guide](/guides/customer-sync),
[webhook guide](/guides/webhooks) or [marketplace OAuth guide](/guides/oauth-marketplace).
Check the [API availability matrix](/support/api-availability) before promising a
workflow: a native integration capability does not imply an equivalent public API.
# Klaviyo
Source: https://developers.perkstar.co.uk/integrations/klaviyo/index
Connect loyalty profiles and events to Klaviyo and verify the correct account.
Use Perkstar loyalty data in Klaviyo segments and flows. This sync connection is
separate from [Resend email delivery](/integrations/resend): it does not change the
account Perkstar uses to send invitation emails.
## Connect
1. Sign in to the intended business with permission to manage integrations.
2. Open **Integrations → Klaviyo → Connect** and review the provider authorisation.
3. Choose the intended Klaviyo account and return to the same Perkstar business.
4. Open **Manage** and confirm the connected account name. Check for any setup or
data-delivery warning before relying on the connection.
Availability depends on the business's access and platform configuration. Do not
create a second active connection to work around an account mismatch.
## Verify the first result
Use an authorised test customer and one supported loyalty action. Compare the
customer's profile properties and corresponding event in Klaviyo with Perkstar's
**Last successful sync**, **Queued events**, **Failed events** and recent delivery
rows. A successful authorisation is not proof that a flow sent an email.
The synchronised data includes customer identity/contact details, cards, balances,
reward activity, join and activity dates, group/birthday and recorded email/SMS
consent properties. Configure your Klaviyo flows to respect those choices. Keep
emails disabled in a test flow unless a controlled test send is intended.
## Recover and disconnect
Inspect failed events and the visible error first. Repair an expired authorisation
through the workspace; do not import the same audience repeatedly to force a
retry. Disconnect through **Manage** when retiring the connection and review any
separately scheduled Klaviyo flows in Klaviyo. Disconnecting does not recall mail
already accepted by that provider. Contact support with the account and event
reference, without customer lists or credentials.
# Lightspeed Restaurant K-Series
Source: https://developers.perkstar.co.uk/integrations/lightspeed-k-series/index
Availability and next steps for Lightspeed Restaurant K-Series.
**Controlled rollout.** Reviewed 13 September 2026. The status shown in the
intended business's dashboard is authoritative for that account.
Reconcile eligible closed restaurant sales and refunds for existing Perkstar members. Access requires explicit release approval and the required provider configuration; an eligible subscription alone does not enable it.
## What to do now
Open **Perkstar → Integrations** and inspect Lightspeed Restaurant K-Series. If it says **Coming soon**
or **Unavailable**, do not use an old setup URL or grant provider credentials to
work around it. Documentation and a provider's developer portal do not themselves
grant access to a Perkstar connector.
If you already have an approved connection, use **My integrations → Manage** where
available. Keep the original provider account and transaction references when
asking support about a failure. Do not disconnect a working installation merely
to test whether you can reconnect it.
## Discuss compatibility with support
Provide the business account number, provider product/version, country, relevant
store or location, and the loyalty workflow you need. Do not share passwords,
API keys or customer lists. Ask support to confirm both access and an appropriate
controlled test before relying on this connection for customer transactions.
For a bespoke connection, start with the [POS guide](/guides/pos) and
[API availability](/support/api-availability). A custom integration is a separate
implementation, not a way to enable an unreleased native connector.
# Lightspeed Retail
Source: https://developers.perkstar.co.uk/integrations/lightspeed/index
Availability and next steps for Lightspeed Retail.
**Not open for new connections.** Reviewed 13 September 2026. The status shown
in the intended business's dashboard is authoritative for that account.
Connect Lightspeed Retail sales and customer activity when the integration is released. The current workspace does not offer general self-service setup for this provider.
## What to do now
Open **Perkstar → Integrations** and inspect Lightspeed Retail. If it says **Coming soon**
or **Unavailable**, do not use an old setup URL or grant provider credentials to
work around it. Documentation and a provider's developer portal do not themselves
grant access to a Perkstar connector.
If you already have an approved connection, use **My integrations → Manage** where
available. Keep the original provider account and transaction references when
asking support about a failure. Do not disconnect a working installation merely
to test whether you can reconnect it.
## Discuss compatibility with support
Provide the business account number, provider product/version, country, relevant
store or location, and the loyalty workflow you need. Do not share passwords,
API keys or customer lists. Ask support to confirm both access and an appropriate
controlled test before relying on this connection for customer transactions.
For a bespoke connection, start with the [POS guide](/guides/pos) and
[API availability](/support/api-availability). A custom integration is a separate
implementation, not a way to enable an unreleased native connector.
# Use Loyverse at checkout
Source: https://developers.perkstar.co.uk/integrations/loyverse/checkout
Show staff how to scan a customer's Wallet card, award points and redeem an exact balance through Loyverse POS.
Staff stay inside the Loyverse POS journey. The customer only needs the branded
loyalty card in Apple Wallet or Google Wallet.
## Find the customer and earn points
Add the sale items in Loyverse as normal.
Tap **Add client** or **Add customer** and scan the QR code on the
customer's Perkstar Wallet card with the device camera or compatible barcode
scanner.
Check the correct profile has opened, then tap **Add to ticket**.
Take payment in Loyverse normally. Perkstar applies the connected card's
automatic earning rule after it receives the paid receipt.
Attach the customer before payment. Perkstar does not guess who made an
unattached purchase and will not award that sale to someone later.
## Redeem some or all of the balance
Add the items, scan the Wallet card and add the matched profile to the
ticket.
Open the customer profile and tap **Redeem points**.
Use the full maximum or enter a lower eligible amount requested by the
customer, then tap **OK**.
Check the point discount under **Discounts**, then tap **Charge** and
complete payment.
Loyverse labels the checkout value as points, but while this integration is
live it represents spendable money. At a GBP till, **5.00 means £5.00**.
Perkstar reads the exact monetary discount from the paid receipt, so entering
£1.25 deducts £1.25—not £0.01 and not the whole available balance.
The customer can spend only the balance currently available. Before the
configured minimum is reached, the spendable balance is zero and the Wallet card
shows the points remaining until it unlocks.
## What the customer experiences
1. Join the business's Points card and add it to Apple Wallet or Google Wallet.
2. Show the Wallet QR code at checkout.
3. Earn points after a paid sale when the customer was attached to the ticket.
4. Once the minimum is reached, choose how much available balance to spend.
5. See updated Points and Balance fields after Perkstar reconciles the receipt
and the Wallet refresh completes.
## When updates appear
Online receipts normally begin syncing when Loyverse sends a receipt update.
If that notification is delayed, Perkstar's five-minute recovery sync looks for
the missing change. The Wallet refresh is queued after the loyalty update and
its display timing can also depend on the Wallet platform and phone connection.
If a POS device takes a sale offline, Perkstar cannot see it until Loyverse
syncs the receipt. Reconnect the device and allow the normal sync to finish. Do
not repeat the sale or make a manual loyalty adjustment to compensate for a
delay.
Loyverse provides illustrated instructions for [scanning a customer
barcode](https://help.loyverse.com/help/scanning-customer-barcode) and [redeeming
points](https://help.loyverse.com/help/points-discounts).
# Move customers and send invitations
Source: https://developers.perkstar.co.uk/integrations/loyverse/customer-migration-invitations
Copy existing Loyverse customers and points safely, choose whether to add welcome points, and invite each customer to install the right Wallet card.
Perkstar can move the existing Loyverse customer directory and current points
without asking the business to prepare and upload a separate spreadsheet.
Nothing is sent to customers automatically: the business reviews the completed
copy first, then chooses email, paid SMS or both.
Customer records, exact Loyverse customer IDs and current points become the
opening Perkstar membership and balance.
Keep imported balances only, or add the card's configured welcome points to
eligible migrated customers.
Invite customers using the included service email, paid SMS after the plan
is active, or both.
## Before starting the copy
In **Loyverse Back Office → Settings → Loyalty**, save the earning percentage
as **0%**. From the Step 2 snapshot until activation finishes, staff must not
redeem old Loyverse points or manually edit customer point balances.
Finalise the Perkstar card's earning, conversion and expiry rules first. The
copy preserves the current Loyverse points; it does not recalculate historical
purchases or infer a different cash value from the old receipt history.
## Review and copy the customers
In Perkstar's Loyverse setup, choose **Check existing Loyverse customers**.
Perkstar shows the source count, customers safe to copy, total opening
points and a short identifying list for any duplicate contacts, invalid
balances or existing customer codes that need attention.
**Keep imported balances only** is selected by default. Alternatively, the
business owner can choose to add the selected card's configured welcome
points once to each eligible migrated membership.
Before approval, Perkstar shows the points per customer, maximum eligible
recipients, maximum additional points, cash-equivalent exposure and the
configured expiry. Customers whose welcome decision was already processed
are skipped, so the same membership does not receive it twice. Failed and
excluded rows receive nothing extra.
Confirm that the business controls the data and is instructing Perkstar to
perform this service migration. This does not grant marketing consent. If
existing Loyverse customer codes are shown, expressly approve their later
replacement with the managed Wallet QR identifiers.
Choose **Copy customers and points**. Perkstar binds each row to the exact
Loyverse customer ID and copies `total_points` as the opening Perkstar
points balance. The work continues safely in the background, and failed
rows can be reviewed and retried without duplicating successful balances or
welcome points.
The saved card and welcome-points choice are locked for this migration. A
retry, interrupted connection or reconnect cannot silently switch the
remaining customers to a different card or policy.
Do not continue to scanning or send invitations while Step 2 shows excluded,
errored or incomplete customers. The setup remains closed until the current
cohort is complete so no customer is invited to a membership that is not ready.
## Invite customers to install the card
When Step 2 says **Customer migration complete**, open the import results. The
business can use either channel or both:
| Channel | Availability | What happens |
| - | - | - |
| Included service email | Available for the completed migration, including during an eligible trial | Sends the ready-made transition message and secure personal install link. It does not consume SMS credits or opt the customer into marketing. |
| Paid SMS | Available after the Perkstar subscription is active and enough SMS credits are available | Shows the exact eligible audience, segments and credit cost before the business confirms the one-time send. |
Perkstar skips customers who have already installed the Wallet card before the
final provider send. Suppressed, opted-out or otherwise ineligible contacts are
not sent through the relevant channel. Starting invitations freezes replacement
of that completed migration; contact Perkstar if a later source correction is
required.
For a first rollout, use **Send one test invitation** before releasing the
full audience. Enter the saved email address or mobile number for one eligible
migrated membership, then review the exact message, recipient and channel.
Email is included; a test SMS needs an active paid plan and the displayed SMS
credit. The test uses the same signed membership link and provider-boundary
checks as its full channel, but it does not consume or close either remaining
audience. After that person installs the Wallet card, Perkstar excludes them
from the later install-invitation audience.
A test invitation is a real customer message, not a preview sent to an
arbitrary address. Send it only to a customer or owner-controlled test
membership that the business is authorised to contact. Once the test link is
released, Perkstar locks that completed migration against replacement so the
link cannot be redirected to a different import.
Perkstar never sends the migration invitation automatically. The business
reviews the result, message and audience, then chooses when to send.
## What the customer receives
Every invitation contains a signed link for one exact migrated membership. It
does not ask Perkstar to find a balance by name or create a second account.
* An email or mobile number already saved in Loyverse is shown read-only so the
customer cannot accidentally detach the Wallet card from the preserved
membership and points.
* If one contact method was missing, the customer can add it to the same
membership before installing the card.
* The customer adds the business's branded card to Apple Wallet or Google
Wallet and shows its QR code at checkout.
* If welcome points were approved and the customer was eligible, the invitation
explains that they were added in addition to the copied opening balance.
## Continue the integration
1. Send one email or paid-SMS test invitation to an owner-controlled migrated
membership and install its Wallet card.
2. Enable **customer card scanning** and wait for **X of Y customers ready**.
3. Resolve every listed customer-code or profile conflict.
4. Test the installed Wallet QR on every POS device using its camera or compatible 2D
scanner.
5. Enable till redemption and wait for the two balance checks and required
15-minute safety period to finish.
6. After the till test passes, review and release the remaining email, paid SMS
or both. Perkstar never sends the broad audience automatically.
For approximately 550 customers, till activation normally takes 30–90 minutes,
depending on Loyverse response time. The page can be closed after activation
starts; Perkstar continues from durable checkpoints. Do not serve customers
through the integration until scanning, earning and redemption all report as
connected.
Continue with [Use Loyverse at checkout](/integrations/loyverse/checkout).
# Loyverse POS
Source: https://developers.perkstar.co.uk/integrations/loyverse/index
Connect Perkstar to Loyverse for Wallet QR scanning, automatic points, exact balance redemption and matched refunds.
Run one complete loyalty journey at the Loyverse till. Staff scan the QR code
on a customer's branded Apple Wallet or Google Wallet card, paid purchases earn
points automatically, and the customer can spend all or part of their available
Points-to-Cash balance during checkout.
Scan the customer's Wallet QR code and attach the matching Loyverse customer
to the ticket.
Perkstar reads the paid Loyverse receipt and applies the earning rules on
the connected Points card.
Redeem the full available balance or enter a smaller amount without leaving
Loyverse POS.
**Set Loyverse's own loyalty earning percentage to 0% before enabling till
redemption.** Perkstar calculates points from the paid receipt. Leaving both
systems earning can reward the same purchase twice.
## What stays in sync
| Event | What Perkstar does |
| - | - |
| Customer scans their Wallet card | Finds or creates the eligible Loyverse customer and links the Wallet QR identifier |
| Paid sale | Applies the connected card's earning rule once |
| Partial or full redemption | Deducts the exact monetary point discount recorded on the paid receipt |
| Eligible refund or cancellation | Reverses applicable earning and restores supported redeemed value once |
| Loyalty balance changes | Refreshes the Wallet card and the spendable value available in Loyverse |
During initial setup, Perkstar also provides a controlled migration that copies
the existing Loyverse customer directory and each customer's current points as
their opening Perkstar balance. It binds migrated members to their exact
Loyverse customer IDs rather than trying to reconstruct old receipt history.
Perkstar is the source of truth for points, spendable balances and loyalty
activity. Loyverse remains the source of truth for sales and refunds.
## What you need
* A Perkstar business and plan that includes the Loyverse integration.
* Owner or manager access in Perkstar and permission to connect apps in the
intended Loyverse business.
* The same two-decimal currency in both systems.
* An active individual **Points card** with automatic earning, a QR code and
flexible Points-to-Cash spending.
* An online Loyverse POS device with camera barcode scanning enabled, or a
compatible external barcode scanner.
Prepare the card, set Loyverse to 0%, connect and activate safely.
Preserve current points, choose whether to add welcome points and invite
customers by included email or paid SMS.
Give staff a clear scan, earn and partial-redemption workflow.
Handle corrections, delayed updates, troubleshooting and disconnection.
## Data flow
| Direction | Information | Purpose |
| - | - | - |
| Loyverse → Perkstar | During initial migration: customer directory, exact customer IDs, contact details, customer code and current points; during normal use: business identity, currency, customer reference, and paid receipt or refund information | Preserve existing members and opening points, match the correct customer, calculate earning, read the exact redemption and reconcile corrections |
| Perkstar → Loyverse | Customer name, email and optional phone when a profile must be created; managed Wallet QR identifier; current spendable balance | Find the customer by scanning and make their balance available through **Redeem points** |
| Perkstar → Wallet platforms | Updated Points, Balance and programme fields | Keep the customer's Apple Wallet or Google Wallet card current |
Products, inventory, employees, taxes and payment information are not
synchronised. Perkstar connects through Loyverse OAuth, so the business does not
share its Loyverse password with Perkstar.
Need help with a live connection? Email
[Loyverse@perkstar.co.uk](mailto:Loyverse@perkstar.co.uk) with the Perkstar
business name, Loyverse receipt number and approximate time. Never send a
password, access token or customer's Wallet QR value.
# Refunds and troubleshooting
Source: https://developers.perkstar.co.uk/integrations/loyverse/refunds-troubleshooting
Reconcile Loyverse refunds, diagnose delayed loyalty updates and disconnect the integration safely.
## Refunds and cancellations
Process a refund or cancellation against the **original Loyverse receipt**.
Perkstar reverses the applicable earning and restores redemption value supported
by that correction. A cancellation is treated as a full correction, and the
same update is safe to receive more than once.
A refund against a sale created before the Step 2 migration snapshot does not
automatically adjust Perkstar points. Historical purchases were represented by
the copied opening balance rather than separate Perkstar receipt credits, so
Perkstar does not reconstruct and then reverse an old sale. Contact
[Loyverse@perkstar.co.uk](mailto:Loyverse@perkstar.co.uk) if the business needs
an opening-balance correction for that historical refund.
If Perkstar cannot safely match the correction to its original sale or determine
the supported amount, it does not invent a points or money adjustment. Only the
affected customer's published balance is held at zero and a review issue appears
on the Loyverse integration page while other receipts continue syncing.
Do not make a manual points or balance adjustment when a refund needs review.
Record the customer, original receipt number and time, then contact
[Loyverse@perkstar.co.uk](mailto:Loyverse@perkstar.co.uk).
## Troubleshooting
Do not enable scanning or send invitations yet. Open the migration result,
use the identifying issue list to correct duplicate contact details, invalid
balances or customer-code conflicts in Loyverse, then run the guided refresh
or retry. Perkstar keeps successful rows and their points safe; a retry does
not grant the opening balance or approved welcome points twice. If
invitations have already started, contact support before changing the source
cohort.
Invitations open only for the exact current migration after every eligible
customer has copied successfully. The included service email can be used
during an eligible trial. Paid SMS requires an active paid subscription and
enough SMS credits; its preview shows the eligible audience, message
segments and credit cost. Customers without a usable contact method cannot
be invited remotely and need a staff-assisted handoff.
Use its **Edit** link under **Needs changes**. Confirm it is an active
individual Points card, earns automatically, uses flexible Points-to-Cash
with a positive minimum, displays a QR code and requires First name and
Email. Save the guided changes and return to Loyverse setup.
Confirm customer scanning is on, the customer joined the selected card, and
the device camera or external scanner is enabled. Check the integration page
for duplicate-email, customer-code or missing-details issues, correct the
record and choose **Retry customer sync**.
Confirm the correct customer was attached before payment, the connected card
is active, the receipt is paid and the POS is online. Check connection
status and the last recovery sync before retrying. Perkstar does not guess
the customer for an unattached receipt.
Flexible Points-to-Cash remains locked until the configured minimum is
reached. The Wallet card shows the points still needed. Also confirm till
redemption has finished activating.
Immediately open **Loyverse Back Office → Settings → Loyalty**, save **0%**
and leave it there. Do not manually edit Loyverse points while Perkstar till
redemption is active. Record the receipt and contact Perkstar support.
Keep the POS online and allow the receipt to sync. Perkstar uses real-time
receipt notifications with a five-minute recovery path, and the Wallet
display can update shortly after the loyalty ledger. Check the dashboard
before repeating an action.
Stop redemption and reconnect the same Loyverse business only after checking
its balances and managed customer codes. If Loyverse access was revoked
first, manually clear any remaining Perkstar-published values before turning
redemption back on.
Perkstar stopped instead of guessing about a changed or uncertain Loyverse
balance. During the first cutover, turn off customer card scanning, wait for
every managed code to be restored, then run the safe recovery check in Step
2\. If that check says the value cannot be verified, do not edit it; contact
Perkstar support. During a later reactivation, review the unexpected old
Loyverse points balance. Retry activation only after you have confirmed it
is safe to return that old Loyverse balance to zero; contact support if the
value may be genuine.
## Frequently asked questions
No. Loyverse requires the complete scan, automatic earn and flexible
monetary redemption journey, so only compatible Points cards are available.
Yes. Once the card's minimum has unlocked spending, staff can enter any
eligible amount up to the available balance and ticket limit. Perkstar
deducts the exact monetary point discount on the paid receipt.
No. Products, inventory, employees, taxes and payment information are not
synchronised. The integration exchanges only the business, customer,
receipt, refund, QR identifier and balance information required for loyalty.
## Disconnect safely
Disconnect inside Perkstar first. Perkstar needs working Loyverse access to
release its scan identifiers, reconcile outstanding receipts and clear the
balance values it published.
Open **Perkstar → Settings → Integrations → Loyverse**, choose **Turn off
card scanning** and wait until the managed customer scan codes are released.
Choose **Disconnect Loyverse**. Perkstar keeps receipt reconciliation active
while it clears and verifies published balances. Resolve any displayed
refund review first.
Keep Loyverse authorised while clearing and verification finish.
Only after Perkstar reports **Disconnected** should you remove the app from
Loyverse Back Office.
Disconnecting does not delete ordinary Loyverse customer profiles or the
business's own Perkstar cardholders. Perkstar deletes the Loyverse credentials
and locally held API-derived copies after disconnection, while retaining the
de-identified Perkstar loyalty and accounting ledger under its normal retention
rules.
Already revoked Perkstar from Loyverse? Manually clear any remaining
Perkstar-published points and managed customer codes before using Loyverse
loyalty again, then contact [Perkstar support](mailto:Loyverse@perkstar.co.uk) for
guidance.
# Set up Loyverse
Source: https://developers.perkstar.co.uk/integrations/loyverse/setup
Prepare a compatible Points card, set Loyverse earning to 0%, connect the businesses and test the complete journey.
Complete every step before serving customers. Perkstar keeps earning and till
redemption off until the required card, scanning and balance checks are ready.
## Before you connect
* Confirm Perkstar and Loyverse use the same currency. Till redemption requires
a currency with two decimal places.
* Sign in as a Perkstar owner or manager and use a plan that includes Loyverse.
* Make sure you can approve apps for the intended Loyverse business.
* Finalise the connected Points card's earning and Points-to-Cash rules before
moving customers. Perkstar copies the current Loyverse points balance; it
does not rebuild value from receipt history.
* Keep every POS device online while configuring and testing it.
Perkstar will not clear an existing Loyverse points balance until its direct
migration has recorded every eligible customer and copied the current points
exactly. Activation then validates the same snapshot, clears the old balances
twice and publishes only each customer's spendable Perkstar balance.
## Prepare the Points card
The card picker shows eligible cards under **Ready to connect**. Cards under
**Needs changes** cannot be selected and include an **Edit** link explaining
what to fix.
A compatible card must be:
* active and unarchived;
* a Points card for individual customers, not a group-enrolment card;
* configured to earn automatically by spend or visit, rather than by manual
points entry;
* configured with an ongoing Points-to-Cash balance and a valid conversion;
* set to flexible spending with a positive minimum balance before spending;
* configured to display a QR code; and
* configured to require **First name** and **Email** on the sign-up form.
Stamp cards, reward-level Points cards, set-amount Points-to-Cash cards,
group-enrolment cards and manual-earning cards cannot be connected. Flexible
Points-to-Cash is required because a cashier can enter any eligible amount up
to the available balance.
## Set Loyverse earning to 0%
Sign in to the same Loyverse business you will connect to Perkstar.
Go to **Settings → Loyalty**.
Set the loyalty earning percentage to **0%**, then select **Save**.
This setting applies across the Loyverse account. Perkstar cannot read or change
it through the Loyverse API, so you must confirm it during activation and leave
it at 0% while the integration is live. See [Loyverse's loyalty
instructions](https://help.loyverse.com/help/how-customer-loyalty-program).
## Connect and activate
[Start the Loyverse
connection](https://dashboard.perkstar.co.uk/install/loyverse), sign in to
Perkstar and choose the business if asked. Authorise access to Loyverse
business details, customers and receipts. On return, check the Loyverse
business name and currency before continuing.
Select the intended card under **Ready to connect**, then choose **Use this
card with Loyverse**. Use the guided **Edit** link if a card is under
**Needs changes**.
In **Step 2**, choose **Check existing Loyverse customers**. Review the
customer count, total points and any named issues. The owner can keep the
copied balances exactly as they are—the default—or approve the card's
configured welcome points for eligible existing customers. Perkstar shows
the maximum points and cash-equivalent exposure before anything starts.
Confirm the data-transfer instruction and, where shown, approve replacing
the exact existing customer codes. Then choose **Copy customers and
points**. Perkstar copies `total_points` as the opening membership balance;
it does not recalculate old purchases. Follow the [customer migration and invitation
guide](/integrations/loyverse/customer-migration-invitations) for the full
transition journey.
Only after Step 2 says the migration is complete, open its results. For the
first rollout, send one controlled included-email or paid-SMS test to an
eligible owner-controlled membership, then complete the till checks below
before releasing the remaining included service email, paid SMS, or both.
Perkstar does not message customers automatically. Every message opens the
exact migrated membership so the preserved balance stays attached to the
right person.
Read and confirm the customer data-sharing notice, then choose **Enable
customer card scanning**. Customers moved in Step 2 remain bound to their
exact Loyverse profiles. Perkstar publishes each managed Wallet QR
identifier and shows live progress as **X of Y customers ready**. Resolve
every listed conflict before till redemption is available. For customers who
join after cutover, Perkstar links one unambiguous exact-email profile or
creates an eligible profile when none exists.
In Loyverse POS, open **Settings → General** and enable **Use camera to scan
barcodes**, unless the device uses a compatible external scanner. Tap **Add
customer**, scan a test Wallet card and confirm the correct customer opens.
Repeat this on every new or replacement device.
On a Teya Android terminal running Loyverse, try the built-in camera first.
A SUNMI Blink or another compatible 2D scanner can be used in USB
HID/keyboard mode when the terminal or dock provides USB host/OTG access.
Test the exact terminal, dock and scanner together before buying or rolling
out hardware.
Confirm separately that every device can scan, Loyverse is set to 0%, and
existing balances may be replaced. Choose **Enable till redemption** and
allow about 20 minutes for a small customer list. A list of around 550
customers typically takes 30–90 minutes; lists above 2,000 can take several
hours. Activation includes a required 15-minute safety wait between two
complete balance checks. You can leave the page after starting because
Perkstar continues safely in the background. Keep Loyverse earning at 0% and
do not let staff redeem or manually edit old Loyverse points from the Step 2
snapshot until activation finishes. Do not serve customers until the page
says scanning, earning and redemption are connected.
## Customer information used for scanning
During the one-time transition, Perkstar reads the existing Loyverse customer
directory, exact customer IDs, contact details, current points balances and
customer codes so the business can preserve its loyalty members and value.
When scanning is enabled, Perkstar sends the customer's name, email address,
optional phone number and managed Wallet scan identifier to Loyverse. Customer
reference IDs, receipts, redemptions and balance data are exchanged to run the
integration. The business must instruct this transfer, tell customers about the
sharing and have an appropriate lawful basis. No marketing consent is inferred.
* [Perkstar privacy policy](https://dashboard.perkstar.co.uk/privacy)
* [Integration recipients](https://dashboard.perkstar.co.uk/dpa/sub-processors)
## Test before going live
Use a synthetic customer and record the expected result for the connected
card's exact earning and conversion rules.
1. Scan the Wallet card through **Add customer**, attach the customer and
complete one paid sale without redemption.
2. Confirm points were added once and the Wallet fields updated.
3. Complete another sale and redeem a smaller amount, such as £1.25 from a
larger available balance.
4. Confirm precisely that amount was deducted—not pennies and not the complete
balance.
5. Refund the second sale against its original receipt and confirm the eligible
correction was applied once.
If setup stops or a button remains unavailable, follow the on-screen
**Before you can continue** list. The Loyverse page can also send a redacted
setup snapshot to Perkstar support and returns a reference number. That
snapshot contains milestones, permission state and aggregate counts only—not
customer contact details, individual balances, access tokens or raw provider
responses.
Continue with the [staff checkout guide](/integrations/loyverse/checkout).
# Mailchimp
Source: https://developers.perkstar.co.uk/integrations/mailchimp/index
Connect a Mailchimp audience and use consenting customers' loyalty data in segments and automations.
Use Perkstar loyalty data to build Mailchimp segments and automations, such as
birthday offers, VIP rewards and reminders for customers who have not visited
recently. You create the emails and automations in Mailchimp.
This integration is in beta on Growth and Scale plans. Availability in your
dashboard depends on deployment and your business's access. Verify the first
result in a dedicated test audience before relying on it for customer campaigns.
## Connect your audience
1. Sign in to the intended Perkstar business with permission to manage integrations.
2. Open **Integrations → Mailchimp → Connect**.
3. [Create a dedicated Mailchimp API key](https://mailchimp.com/help/about-api-keys/)
and paste it into the connection form. Perkstar encrypts the key and does not
display it after saving. Do not send it to support or paste it into a chat.
4. Load your audiences and select the one that should receive loyalty customers.
5. Review any automations already running for that audience, then enable sync.
Adding or updating contacts can trigger those automations. Start with a
dedicated test audience when verifying the connection.
Perkstar adds nine audience fields for its loyalty data. It leaves unrelated
fields alone. If a Perkstar field already exists with an incompatible type, the
setup screen explains which field needs attention.
One Mailchimp account and one audience can be linked to each business. Contact
support to change either after setup so existing unsubscribe history is preserved.
## What syncs
Customers need a valid email address, current email-marketing consent and a loyalty
enrollment. Customers without consent, deleted or anonymized customers and test
pass addresses are excluded.
| Audience field | Value |
| - | - |
| Email | Customer email address |
| `PSFIRST` / `PSLAST` | First and last name |
| `PSPOINTS` | Total points balance across active points cards |
| `PSSTAMPS` | Total stamp balance across active stamp cards |
| `PSREDEEM` | Rewards redeemed across active enrollments |
| `PSCARDS` | Active card names |
| `PSTIER` | Current loyalty and membership tiers |
| `PSACTIVE` | Latest activity date across active enrollments |
| `PSBDAY` | Birthday month and day, without the year |
Existing eligible customers sync in batches. Customer and enrollment changes are
queued automatically; the background worker runs every minute. **Sync now**
processes a batch immediately when the connection is ready, with any remainder
continuing in the background. Card and tier configuration changes are reconciled
daily. Large audiences or provider retries can take longer.
Use these fields in Mailchimp to select customers and configure automations.
Perkstar does not create campaigns or send a history of individual loyalty events
through this connection. Phone numbers, addresses, notes and wallet links are not
exported.
## Check consent and the first result
Use a consenting test customer with a loyalty enrollment. Enable sync and compare
their audience fields in Mailchimp with their Perkstar profile. Change their points
balance and verify the next update. Confirm that a non-consenting test customer is
absent. Connection success alone does not mean an email was delivered.
An existing Mailchimp unsubscribe remains in effect when loyalty data changes.
Perkstar never automatically resubscribes an existing member. New contacts follow
the audience's double opt-in setting; Mailchimp may send a confirmation email and
keep them pending until they confirm.
Withdrawing consent in Perkstar, anonymizing or deleting a linked customer queues
an unsubscribe in Mailchimp. Changing email unsubscribes the former address before
syncing the new one. Mailchimp opt-outs do not change the customer's other Perkstar
messaging preferences.
## Recover, pause or disconnect
Open **Manage** to review the connected account, audience, sync counts and recent
issues. Temporary failures retry automatically. Reconnect with an active API key
if Mailchimp rejects the stored key. Resolve duplicate customer emails in Perkstar
before retrying those customers.
Pausing or disconnecting stops future sync calls, including consent withdrawals.
It leaves existing Mailchimp contacts and automations in place, so manage those in
Mailchimp as needed. A request already in progress may finish. Disconnect clears
the key held by Perkstar; revoke the dedicated key separately in Mailchimp if it is
no longer needed. Reconnect to the same account and audience to resume.
# Make data and security
Source: https://developers.perkstar.co.uk/integrations/make/data-security
Understand OAuth scopes, personal-data flow, consent, Make retention surfaces, and shared responsibilities.
Perkstar for Make uses OAuth with tenant-scoped access. The person connecting
the app approves one Perkstar business; the resulting Make connection cannot
read or write another business. Do not share a raw Perkstar API key with a
scenario builder, contractor, or destination app.
## OAuth permissions
The private-beta Make OAuth client requests these eight baseline scopes for the
guided modules:
| Scope | Why the app needs it |
| - | - |
| `CUSTOMERS_READ` | Find customers and return current customer fields needed by searches and guided workflows. |
| `CUSTOMERS_WRITE` | Create or update customers through the explicit guided actions. |
| `ENROLLMENTS_READ` | Find a customer/card relationship, balance, status, and available Wallet links. |
| `CARDS_READ` | Populate dynamic Card selectors and validate card-aware modules. |
| `EVENTS_READ` | Read bounded recent event samples where the trigger setup requires them. |
| `WEBHOOKS_WRITE` | Create/delete app-owned subscriptions and attest signed deliveries behind attached Make webhooks. |
| `MARKETPLACE` | Enrol customers, record supported loyalty activity, and reverse eligible marketplace transactions. |
| `PUSHES_WRITE` | Send one consent-checked Wallet push through the explicit action. |
The registered client also permits five **optional advanced scopes**. They are
not granted silently: the person creating the Make connection must explicitly
request the required advanced scope and approve it on Perkstar's consent screen.
| Optional scope | Advanced public API use |
| - | - |
| `ENROLLMENTS_WRITE` | Call a documented public enrolment mutation without a guided module. |
| `TRANSACTIONS_READ` | Read a supported transaction resource through **Make an API Call**. |
| `TRANSACTIONS_WRITE` | Call a supported direct transaction write after designing retry protection. |
| `WEBHOOKS_READ` | Read supported app-owned webhook resources through the public API. |
| `LOCATIONS_READ` | Read the connected business's supported location resources. |
Granting all 13 allowed scopes is not required for ordinary guided scenarios.
Choose only the optional access required by the documented universal call. To
add an advanced scope later, update or replace the Make connection and approve
the expanded consent before running the scenario; an existing token does not
gain it automatically.
The connection cannot inspect or mutate webhook endpoints owned by another
OAuth application or user. Perkstar enforces tenant, plan, account state,
consent, card type, input validation, idempotency, and rate limits again when a
module runs.
**Make an API Call** uses the exact scopes granted to that connection: the eight
baseline scopes plus only the optional scopes the user selected. The module
does not grant every allowed scope merely because the OAuth client permits it,
and it cannot call private dashboard routes or switch businesses.
## Data the app can process
| Feature | Potential Perkstar data | Why it is used |
| - | - | - |
| Watch loyalty events | Event ID/type/time, organisation ID, and event-specific customer, card, enrolment, loyalty, purchase, membership, engagement, or booking fields | Start the selected scenario and expose mapping fields. |
| Search customers | Customer ID/number, contact/profile fields, consent flags, external reference, and lifecycle timestamps | Return current customers matching optional exact contact/reference/pass filters or Created after. |
| Search enrolments or passes | Customer/Card IDs, status, balance/activity values, and available Wallet install URLs | Return current programme relationships matching optional Customer ID, Card, and Status filters. |
| Customer actions | Identity, profile, consent, and external-reference fields explicitly mapped by the builder | Create or update the intended customer. |
| Loyalty actions | Customer lookup, Card, amount/delta, stable source reference, note, and selected metadata | Enrol, record one compatible activity, redeem, or reverse the original transaction. |
| Wallet push | Enrolment, message, resolved merge fields, source event ID, and delivery result | Send one business-authored message to eligible Wallet passes. |
| Make an API Call | Request and response fields of the selected supported public v1 operation | Cover a documented operation without a guided module. |
Perkstar does not enrich every event with customer email, name, or phone merely
to make mapping convenient. Use a search only when current profile data is
necessary and authorised. The exact event fields are in the [webhook event
catalogue](/reference/webhook-events).
## Where Make can retain data
Depending on the scenario, workspace settings, plan, and connected apps,
customer data can appear in:
* scenario module inputs and output bundles;
* execution history and incomplete executions;
* webhook queues;
* Make Data Stores, variables, aggregators, and error handlers;
* copied blueprints, screenshots, or support exports; and
* every destination app and its own logs, backups, and retention.
Turning a scenario off or revoking OAuth stops future work but does not
automatically erase those copies. Configure access and retention in Make and
every destination according to the business's policy; do not rely on Perkstar
to delete records after they leave its platform.
## Responsibility model
```mermaid theme={null}
flowchart LR
Customer["Cardholder"] --> Business["Business using Perkstar\nNormally the controller"]
Business --> Perkstar["Perkstar\nNormally a processor"]
Business --> Make["Make organisation and connected apps\nChosen by the business"]
Perkstar --> Make
Make --> Destination["Scenario destinations"]
```
The business determines its legal role and purpose for each destination,
limits who can edit scenarios or inspect executions, gives required notices,
and handles access, correction, deletion, objection, and consent rights across
all copies. Perkstar cannot govern a module after data enters Make.
## Consent and messaging
* Loyalty enrolment is not automatic email, SMS, advertising, profiling, or
Wallet push-marketing consent.
* Treat Perkstar consent fields as purpose-specific state, not blanket
permission for every scenario destination.
* Retain the source, wording, time, and lawful basis needed to support any
consent assertion written from another application.
* **Send a Wallet push** enforces push-marketing consent. A `403` is a safety
outcome, not an error to route around.
* Never place passwords, payment-card data, health data, or other sensitive
free text in a loyalty note, push, Make variable, Data Store, or support
request.
## Minimise and protect
1. Map only fields the next module needs.
2. Prefer opaque Perkstar IDs to copying a full customer profile.
3. Keep production connections and scenarios in the intended Make team; grant
edit and execution-history access only to authorised members.
4. Keep the private Make webhook URL, OAuth tokens, Wallet install links, and
customer payloads out of logs, screenshots, blueprints, and tickets.
5. Use separate test and live source-reference namespaces.
6. Review routers and error handlers: a failed privacy/consent filter must not
fall through to a sending route.
7. Protect Data Stores and destination records with retention/deletion rules,
not indefinite defaults.
## Webhook authentication boundary
Perkstar signs outbound webhooks with HMAC-SHA256. Because Make exposes parsed
JSON rather than the exact signed bytes, the official instant module performs
an authenticated server-attestation request before emitting a bundle. Perkstar
binds the proof to the app-owned webhook, OAuth application and user,
organisation, delivery ID, signing time, signature, and event envelope. The
signing secret remains encrypted in Perkstar and is not copied into Make.
Keep the unique Make callback URL secret as an additional control. A failed or
incomplete attestation must be investigated; do not route around it or map the
unverified receiver payload directly. See [Webhooks and instant
scenarios](/integrations/make/webhooks).
## Disconnect, deletion, and rights requests
Deleting an attached Make webhook removes its corresponding app-managed
Perkstar subscription. Revoking the connection stops future authorised API
calls. Neither action automatically deletes:
* Make execution history, incomplete executions, or queued/processed bundles;
* Make Data Store entries or copied scenario/blueprint data;
* records created in a CRM, spreadsheet, chat tool, or another destination; or
* Perkstar source records the business is otherwise entitled or required to
retain.
For a rights request, locate data by Perkstar ID and stable external reference,
then perform the required export, correction, suppression, or deletion in
Perkstar, Make, and every destination. Test this procedure before a live
scenario distributes personal data.
## Production review
* [ ] Beta access, scenario owner, Make team, Perkstar tenant, and destinations
are documented.
* [ ] The OAuth connection uses the correct business and no raw API key exists
in a module or variable.
* [ ] The scenario maps the minimum necessary fields.
* [ ] Consent and suppression behaviour is tested.
* [ ] Editors, connection users, execution viewers, and Data Store access are
restricted.
* [ ] Stable references make customer and transaction writes retry-safe.
* [ ] Webhook URL secrecy and server-attested delivery rejection are tested.
* [ ] Revocation, attached-webhook deletion, queue handling, destination
deletion, and rights requests are tested.
Report suspected credential exposure, unauthorised access, or a personal-data
incident to [privacy@perkstar.co.uk](mailto:privacy@perkstar.co.uk). For an
operational failure, follow [Make troubleshooting](/integrations/make/troubleshooting).
# Make
Source: https://developers.perkstar.co.uk/integrations/make/index
Build visual Perkstar scenarios with one instant loyalty-event trigger, guided loyalty modules, searches, and secure OAuth.
Connect Perkstar loyalty activity to the applications in a Make scenario. The
app has one dynamic **Watch loyalty events** instant trigger with
29 event choices, 11 guided actions, two searches, and the required **Make an
API call** universal module. Card and event selectors load choices from the
connected Perkstar business, so builders normally map names and IDs without
copying raw API requests.
The official Perkstar app for Make is currently a **private beta**. It is not
published in Make's public app catalogue. Access must be enabled by Perkstar
for the intended Make organisation; finding a similarly named public app or
being on an eligible Perkstar plan does not grant beta access.
Authorise one Perkstar business with OAuth. Do not paste an API key into a
scenario or share one with a contractor.
Choose one loyalty event per instant module, with optional card and
live/test filtering where supported.
Use guided modules, stable source IDs, idempotent retries, and explicit
consent checks in production scenarios.
## Availability
| Item | Current position |
| - | - |
| Make listing | Private-beta custom app; not published in Make's public app catalogue |
| Perkstar plan | Growth, Scale, Enterprise, or Franchise |
| Connection | Perkstar OAuth; one Perkstar business per Make connection |
| Permissions | A Perkstar owner or authorised team member who can connect integrations |
| Visible modules | 15: one instant trigger, 11 guided actions, two searches, and one universal API module |
| Trigger coverage | 29 public business events through one dynamic **Watch loyalty events** module |
Private-beta access and plan eligibility are separate. An eligible business
still needs explicit beta access until Perkstar completes Make review and
publishes the app.
## Module map
```mermaid theme={null}
flowchart LR
Perkstar["Perkstar business"] --> Watch["Watch loyalty events\n29 event choices"]
Watch --> Scenario["Make scenario\nfilters, routers, and mappings"]
Scenario --> Apps["Connected destination apps"]
Apps --> Actions["11 guided Perkstar actions"]
Scenario --> Searches["2 Perkstar searches"]
Scenario --> Universal["Make an API call\nadvanced public v1 operations"]
```
The guided actions cover customer creation and updates, explicit find-or-create
and find-or-enrol flows, loyalty earning and redemption, transaction reversal,
and consented Wallet pushes. **Make an API call** is for supported public v1
operations that do not yet have a guided module; it does not bypass OAuth
scopes, tenant boundaries, plan checks, validation, or consent.
## What stays authoritative
Perkstar remains the system of record for customers, enrolments, Wallet passes,
loyalty balances, rewards, and outbound events. Make stores scenario
configuration, execution records, webhook queues, and any values copied into
other modules.
| Direction | What happens |
| - | - |
| Perkstar → Make | A selected Perkstar event sends one bundle to the instant trigger. |
| Make → Perkstar | A guided or universal module calls a supported public v1 operation using the selected OAuth connection. |
| Make → another app | The scenario sends only the fields its builder maps into that module. |
| Another app → Perkstar | The scenario writes only fields accepted by the selected Perkstar module and connected business. |
Perkstar cannot inspect or control later modules in a scenario. The business is
responsible for the destination app, mappings, lawful purpose, access,
retention, and deletion of copied customer data. Read [Data and
security](/integrations/make/data-security) before processing personal data or
sending marketing messages.
## Start here
Review private-beta prerequisites, approve OAuth, and run a controlled first
scenario.
See every event choice, guided action, search, required input, and important
boundary.
Learn subscription lifecycle, server-attested delivery verification,
retries, duplicate protection, and queues.
Diagnose access, OAuth, trigger, module, rate-limit, consent, and incomplete
execution failures without exposing secrets.
Beta questions are handled through
[support@perkstar.co.uk](mailto:support@perkstar.co.uk). Include the Perkstar
business name and approximate UTC time, but never send an OAuth token, Make
webhook URL, customer payload, or unredacted execution screenshot.
# Triggers, actions, and searches
Source: https://developers.perkstar.co.uk/integrations/make/modules
The complete Perkstar module catalogue for Make, with inputs and safety boundaries.
The published review candidate contains 15 visible modules: one instant trigger with 29
event choices, 11 guided actions, two searches, and one universal API module.
Dynamic selectors load current active cards and other choices from the selected
Perkstar OAuth connection.
The app is available by invite link while Make reviews its Marketplace
listing. Event payloads can gain new optional fields; map only the fields a
scenario needs and handle absent or `null` values.
## Instant trigger
**Watch loyalty events** creates one attached Perkstar webhook for the event
selected in that module. Use separate trigger modules/scenarios for different
event subscriptions; do not subscribe to every event merely to discard most
bundles later. The trigger outputs a bundle only after an authenticated
Perkstar attestation binds its subscription, OAuth owner, signed delivery
headers, timestamp, and event envelope.
### Customer lifecycle
| Event choice | Perkstar event | Fires when |
| - | - | - |
| New customer enrolment | `customer.enrolled` | A customer first joins a loyalty card. |
| Customer unenrolled | `customer.unenrolled` | Access to a card ends. |
| Customer anonymised | `customer.anonymized` | Perkstar removes the customer's direct identifiers. |
| Customer lifecycle group changed | `customer.group_changed` | A customer moves between Perkstar's six exclusive lifecycle groups. |
The lifecycle-group event does not represent an operator-created saved segment.
Perkstar stores the first classification as a baseline without emitting an
event, preventing a newly connected scenario from replaying every customer.
### Wallet, scanner, expiry, and referrals
| Event choice | Perkstar event | Fires when |
| - | - | - |
| Wallet pass installed | `wallet.installed` | Perkstar first observes an Apple or Google Wallet install; Google observation is periodic. |
| Card scanned | `card.scanned` | An online Perkstar Scanner lookup successfully resolves a card; offline cache-only lookups do not fire. |
| Customer card expired | `card.expired` | One enrolment reaches its effective expiry; a later expiry after extension can produce another event. |
| New customer referral | `referral.created` | One customer refers another customer to the same loyalty-card programme. |
`referral.created` is customer-to-customer loyalty activity. It is not a
merchant, agency, partner, or affiliate-referral event.
### Loyalty activity
| Event choice | Perkstar event | Fires when |
| - | - | - |
| New loyalty transaction | `transaction.created` | A supported loyalty-ledger row commits, including a compensating reversal. |
| Coupon redeemed | `coupon.redeemed` | A coupon card is redeemed. |
| Reward redeemed | `reward.redeemed` | A reward, offer, voucher, or milestone is redeemed. |
| Loyalty tier changed | `tier.changed` | A status, cashback, or discount tier changes. |
### Tickets, gifts, and multipasses
| Event choice | Perkstar event | Fires when |
| - | - | - |
| Ticket purchased | `ticket.purchased` | Paid ticket fulfilment completes. |
| Ticket cancelled | `ticket.cancelled` | A ticket event is cancelled. |
| Ticket refunded | `ticket.refunded` | A ticket payment is refunded or lost to chargeback. |
| Gift card purchased | `gift.purchased` | Paid gift fulfilment completes. |
| Gift card redeemed | `gift.redeemed` | Value is spent from a gift card. |
| Multipass purchased | `multipass.purchased` | A multipass is purchased or topped up. |
### Memberships
| Event choice | Perkstar event | Fires when |
| - | - | - |
| Membership purchased | `membership.purchased` | A recurring or one-off membership first activates. |
| Membership renewed | `membership.renewed` | A recurring membership advances to a new billing period. |
| Membership cancelled | `membership.cancelled` | A recurring membership becomes cancelled or incomplete-expired. |
### Engagement
| Event choice | Perkstar event | Fires when |
| - | - | - |
| Feedback submitted | `feedback.submitted` | A customer submits card feedback. |
| Automation fired | `automation.fired` | A Perkstar automated-message firing is recorded. |
| Broadcast sent | `broadcast.sent` | A Wallet broadcast reaches terminal delivery processing. |
### Bookings
| Event choice | Perkstar event | Fires when |
| - | - | - |
| Booking created | `booking.created` | A booking is created. |
| Booking confirmed | `booking.confirmed` | A booking moves to confirmed. |
| Booking attended | `booking.attended` | Attendance is recorded. |
| Booking marked as no-show | `booking.no_show` | A booking is resolved as a no-show. |
| Booking cancelled | `booking.cancelled` | A booking is cancelled. |
The diagnostic `webhook.test` event is deliberately excluded. See the
[webhook event catalogue](/reference/webhook-events) for every required,
optional, and nullable event field.
### Trigger inputs and output
| Input | Behaviour |
| - | - |
| Event | Required. Creates a subscription for exactly one of the 29 event types above. |
| Card | Optional. Use it only when the selected event carries a Card ID; otherwise leave it blank. A blank Card accepts the selected event across all cards. |
| Include test events | Available on the trigger and off by default. It affects only event types that can carry test activity; enable it only in an isolated test scenario. |
Each bundle preserves the common event envelope: stable **Event ID**, dotted
**Event type**, source **Created**, **Organisation ID**, and a nested **Event
data** collection containing the selected event's fields. **Created** is an
integer containing Unix seconds. The nested `data.occurredAt` field is the same
business occurrence time in ISO 8601 text form. Neither value is the time Make
received or executed the scenario. For booking events, `data.id` stays inside
**Event data** and does not replace the outer Event ID. Trigger bundles are
snapshots; use a search only when a later step genuinely needs current customer
or enrolment state.
The module publishes a static synthetic sample so mapping fields are available
without reading a real customer's latest event. Live webhook deliveries use
the same envelope and still complete Perkstar's server-attested verification
before Make emits a bundle.
## Guided actions
The guided modules validate common merchant workflows and are preferred over
the universal API module. A focused loyalty action filters its Card selector to
compatible active programmes and validates a mapped Card ID again at runtime.
| Guided action | What it does | Important boundary |
| - | - | - |
| Create a customer | Creates a customer using the supplied identity fields. | Requires a stable **Unique request ID** and at least one of email, phone, or external reference. Keep the request ID unchanged only when retrying that same create. |
| Find or create a customer by external reference | Looks up one exact external reference and creates the customer only when no match exists. | External reference is required and must remain stable in the source system. It does not fuzzy-match email, phone, or name. |
| Update a customer | Updates explicitly mapped profile or consent fields on one existing customer. | Requires Customer ID. Map at least one field. It cannot change external reference; omitted fields are not an instruction to blank them. |
| Find or enrol a customer in a card | Resolves the customer and returns an existing active customer/card enrolment, or enrols the customer in the selected card. | A revoked or inactive pair is not silently reactivated. Creating a missing customer must be explicitly enabled and pass identity validation. |
| Add a stamp or visit | Adds a positive whole number of stamps or visits to an active Stamp or Multipass card. | Requires a stable Source activity ID. Incompatible or inactive cards are rejected. |
| Award points | Adds a positive points value, including up to two decimals when the card supports it. | Its selector shows active Points cards. The award cannot exceed 100,000; a stable Source points award ID is required. |
| Record a purchase | Records a positive integer minor-unit purchase on an active Cashback or Discount card. | Do not pass a decimal currency amount. A stable Source order or payment ID is required. |
| Redeem loyalty balance | Deducts a positive whole-number balance or prepaid visit without allowing the balance below zero. | Supports active Stamp, Points, Cashback, and Multipass cards; it excludes Coupon, Membership, Discount, Gift, and Ticket flows. |
| Record loyalty activity (advanced) | Selects a compatible `STAMP`, `REDEEM`, `CHECK_IN`, `DISCOUNT`, or `POINTS` activity dynamically. | Card, activity type, and stable Source transaction ID are required. Prefer a focused module when the activity type is known. |
| Reverse a loyalty transaction | Writes one compensating transaction for an eligible marketplace transaction found by Perkstar transaction ID or its stable original reference. | A transaction can be reversed once. The module does not edit or delete the original ledger row and does not infer partial-refund policy. |
| Send a Wallet push | Sends a plain-text message of up to 180 characters to one enrolment's eligible Wallet passes. | Enrolment and stable Source event ID are required. Push-marketing consent and a three-minute per-card cooldown are enforced; API success cannot guarantee device display. |
### Loyalty identity and retries
For **Add a stamp or visit**, **Award points**, **Record a purchase**, **Redeem
loyalty balance**, and **Record loyalty activity (advanced)**, keep the source
module's order, payment, attendance, or redemption ID unchanged when Make
retries an incomplete execution. Perkstar gives each module/operation its own
deduplication namespace and permanently binds the canonical source reference to
the first customer, card, operation, and amount.
An exact retry returns the original result. Reusing that reference with
different inputs produces a conflict instead of changing the first
transaction. Do not replace a stable source ID with `now`, a random UUID, or a
new Make execution ID on retry.
The Wallet push supports `{firstName}`, `{lastName}`, `{balance}`, `{cardName}`,
`{installLink}`, `{shareLink}`, and `{orgName}` merge fields. Map the source
bundle's stable record or event ID into **Source event ID** so repeated handling
of one event is collapsed inside Perkstar's idempotency window.
## Searches
| Search | Matching behaviour | Result |
| - | - | - |
| Search customers | Optional exact email, phone, external reference, or pass barcode/serial filters, plus an optional Created after. | Current matching customers, up to the configured Limit. |
| Search enrolments or passes | Optional Customer ID and Card filters. Status defaults to Active even when the field is left blank or an empty value is mapped. | Active enrolments, balance/activity values, and available Apple/Google Wallet links, up to the Limit. Choose Inactive or Revoked when historical passes are needed. |
Searches do not create or change data. If a no-match should create a customer,
use **Find or create a customer by external reference** with a genuine stable
external reference. If it should create a card relationship, use **Find or
enrol a customer in a card**. Keep a Make router/filter for business outcomes
that should stop, notify an operator, or follow a different path on no match.
Both searches cursor-page and return no more bundles than **Limit**. Limit
defaults to 10 and accepts 1–3,200.
Dynamic Card selectors return up to 500 active cards. Their Limit defaults to
200 and accepts 1–500. General selectors show every active card within that
limit; focused action selectors show only compatible card types. A manually
mapped ID still goes through the same tenant, active, and type checks when the
module runs.
## Make an API call
**Make an API call** is the universal module required for a public Make app. Use
it only when the operation exists in Perkstar's [public API
reference](/api-reference/customers/list-customers) and no guided module fits.
* Enter a path relative to `https://dashboard.perkstar.co.uk/api/v1`, for
example `/customers/{customerId}`. Do not enter a different host or a full
callback URL.
* Select the supported HTTP method and supply only the documented query string
and JSON body. The module supplies OAuth authentication and deliberately does
not expose arbitrary request headers. Keeping authentication and transport
control headers app-owned prevents a scenario from replacing the OAuth
credential, host, content type, or other security-sensitive values.
* For a supported POST, map a stable value of at most 255 characters into the
optional dedicated **Idempotency key** field. The app sends it only as
`Idempotency-Key`; a random value per Make retry can duplicate a write.
* The exact scopes granted to the connection still apply. Guided connections
use eight baseline scopes; five additional advanced scopes are optional and
require explicit selection and renewed OAuth consent. The module cannot
access private dashboard routes, another Perkstar business, or an operation
outside that connection's granted scopes.
* Handle `4xx`, `429`, and `5xx` responses deliberately. Prefer a guided module
for loyalty writes because it also constructs and validates the permanent
source transaction identity.
A universal API module is not a security or product-boundary escape hatch. Do
not use it to recreate an unsupported card editor, bulk-marketing sender, or
undocumented dashboard workflow.
## Deliberately not exposed
* No module edits card configuration, rewards, tiers, coupons, or orders.
* No module bypasses Perkstar consent, plan, card-type, tenant, account-state, or
rate-limit checks.
* `webhook.test` is not a choice in **Watch loyalty events**.
* An event bundle does not promise customer email, name, or phone unless the
documented event carries it.
* Searches and dynamic selectors never read another business connected to the
same Make organisation.
# Make scenario recipes
Source: https://developers.perkstar.co.uk/integrations/make/recipes
Reliable Perkstar scenario patterns for onboarding, loyalty activity, operations, and consented Wallet messaging.
These are private-beta patterns, not public one-click Make templates. Build them
with the named modules, test with controlled records, and define an error route
before processing production customers.
## Send a new member to a CRM or sheet
**Trigger:** Watch loyalty events → New customer enrolment
**Then:** Make an API Call (`GET /customers/{customerId}`) → create or update
the destination record
1. Select a Card in the trigger if the destination represents one programme.
2. When **Event Data** includes Customer ID, use it in the relative API path;
do not make a second identity guess from name, email, or phone. Route an
event with no Customer ID to review or a workflow that can resolve its
documented enrolment context.
3. Make the read only when the destination genuinely needs current profile
fields. **Search customers** does not accept Customer ID; it is for optional
exact email, phone, external-reference, pass-serial, and Created after
filters.
4. Use the Perkstar customer or enrolment ID as the destination's stable external
key.
5. Add a route for a `404` or missing Customer ID rather than creating an
unidentified destination record.
Joining a loyalty card is not blanket consent for email, SMS, advertising, or
another app's marketing list. Map purpose-specific consent only when the
business has evidence for that destination and channel.
## Create an external lead once, then enrol them
**Trigger:** A qualified lead, booking, or checkout in another Make app
**Actions:** Find or Create a Customer by External Reference → Find or Enrol a
Customer in a Card
1. Map the source app's immutable customer/contact ID into **External
Reference**. Namespace it when multiple stores can produce the same value,
for example `hubspot:portal-42:contact:1042`.
2. Map only the identity/profile fields authorised for Perkstar.
3. Select the intended active Card explicitly.
4. Map the returned customer into **Find or Enrol a Customer in a Card**.
5. Store returned Customer ID and Enrolment ID in the source system where
possible.
6. If Wallet links are initially unavailable, use **Search enrolments or
Passes** later with Customer ID, Card, and Active status instead of
constructing a link.
This pattern makes a repeated source event return the same customer and active
customer/card relationship. It never silently reactivates an inactive or
revoked enrolment.
## Record a paid order exactly once
**Trigger:** A paid or completed order in a commerce/POS module
**Action:** Add a stamp or visit, Award points, or Record a purchase
Choose the focused action that matches the Perkstar card:
| Card intent | Guided module | Amount |
| - | - | - |
| Stamp or visit credit | Add a stamp or visit | Positive whole-number count |
| Direct points award | Award points | Positive points value |
| Cashback/discount spend | Record a purchase | Positive integer minor units, such as `1250` for £12.50 |
Map the upstream order/payment ID into the action's Source ID. Prefix it when
several stores can emit the same numeric ID:
```text theme={null}
shopify:store-12:order:94721
```
Use a Make error handler that keeps that value and every fingerprinted input
unchanged on retry—including customer identity, Card, activity type, amount,
note, metadata, and create-if-missing fields. If the scenario needs to choose
an activity type dynamically, use **Record loyalty activity (advanced)** and
validate Card, type, delta, and purchase amount on every route.
Never generate a new source transaction ID when an incomplete execution is
retried. A stable upstream ID is what prevents a delayed or duplicate order
bundle from crediting loyalty twice.
## Reverse a refunded order
**Trigger:** A completed refund in the source app
**Action:** Reverse a Loyalty Transaction
Prefer the Perkstar transaction ID returned and stored by the original earn
scenario. If only the original source order/payment ID is available, use the
same value and the exact original Perkstar operation when the module asks for
it. Perkstar writes a compensating ledger row and returns the existing reversal
when the same original transaction was already reversed.
Partial-refund rules vary. Decide whether a partial refund should leave the
original loyalty transaction, reverse it fully, or be handled by a separate
approved adjustment before activating the scenario. The reversal module does
not infer this policy from arbitrary refund data.
## Route an operational loyalty event
**Trigger:** Watch loyalty events → Reward redeemed, Loyalty tier changed,
Feedback Submitted, Booking Marked as No-Show, or another selected event
**Then:** Filter → approved operations channel or case-management app
Include the Perkstar event ID, source time, and only the opaque customer,
enrolment, booking, or card ID an authorised operator needs. Avoid copying full
contact details or free-text feedback into a broad channel. Use separate
trigger modules/scenarios for materially different access and retention rules.
## Send a consented Wallet reminder
**Trigger:** A deliberate business rule in another app
**Actions:** Search enrolments or passes → Send a Wallet push
* Target one current enrolment.
* Map the upstream bundle's stable event/record ID into **Source Event ID** and
preserve it across retries.
* Keep the expanded message at or below 180 characters.
* Expect `403 push_marketing_consent_required` when consent is absent; route it
to a safe stop, not a workaround.
* Respect `Retry-After` and the shared three-minute per-card cooldown on `429`.
* Do not iterate a large customer list into rapid sends without an approved
frequency cap and queue.
## Use Make an API Call without duplicating a write
Use **Make an API Call** only for a documented public v1 operation without a
guided module.
1. Confirm the operation and schema in the [API reference](/api-reference/customers/list-customers).
2. Use the relative path, never another host.
3. For supported POST requests, map a stable upstream value of at most 255
characters into the optional dedicated **Idempotency Key** field, and keep
it unchanged for every retry of that logical request.
4. Add an error route for `429` and transient `5xx` results.
5. Treat `400`, `403`, `404`, `409`, and `422` as state or validation problems,
not blind-retry candidates.
6. Inspect the Perkstar record after a timeout before changing any identifier.
Prefer a guided module whenever it exists. The universal module cannot add
product-specific card filters or construct the permanent source transaction
identity as safely as the focused loyalty actions.
## Production checklist
* [ ] The Make organisation, team, scenario owner, Perkstar business, and every
destination owner are recorded.
* [ ] Each connection name identifies the tenant and environment.
* [ ] Each instant trigger selects one event and an explicit Card where useful.
* [ ] Every loyalty write uses a stable source ID and survives a duplicate test.
* [ ] Routers handle empty search results and optional event fields.
* [ ] Error handlers preserve original IDs and expose terminal failures to an
operator.
* [ ] Consent and suppression are tested with both allowed and blocked records.
* [ ] `429`, non-retryable `4xx`, incomplete executions, and destination
failures are monitored.
* [ ] Scenario history, webhook queues, Data Stores, and destinations have
intentional retention and access.
* [ ] Disconnect, rights-request, incident, and downstream deletion procedures
have named owners.
For failures, use [Make troubleshooting](/integrations/make/troubleshooting).
# Connect Perkstar to Make
Source: https://developers.perkstar.co.uk/integrations/make/setup
Get private-beta access, authorise Perkstar with OAuth, and test a controlled first Make scenario.
The private-beta app uses Perkstar OAuth. The person creating the connection
signs in to Perkstar, confirms the intended business, reviews the requested
access, and approves it. Make receives revocable OAuth tokens; the builder is
never asked to paste a Perkstar API key into a scenario.
Perkstar for Make is not yet public in Make's app catalogue. Use only the
private app access supplied by Perkstar. A similarly named app or setup page
that asks for a raw Perkstar API key is not the official connection flow.
## Before you connect
* The Perkstar business is on Growth, Scale, Enterprise, or Franchise.
* Perkstar has enabled the intended Make organisation for the private beta.
* You can sign in to both the intended Perkstar and Make accounts.
* Your Perkstar role can connect integrations for the business.
* Your Make role can create connections and edit scenarios in the intended
team.
* At least one active loyalty card exists for card-aware modules and filters.
* You know who will own the scenario and which customer fields each destination
needs.
One Make connection represents one Perkstar business. Create a separately
named connection for every business; a connection never searches or writes
across Perkstar tenants.
## Create the connection
Sign in to the Make organisation that Perkstar enabled and create or open a
scenario in the correct team. Add a module, search for **Perkstar**, and
select a trigger, action, or search. Beta access makes the private app
available to that organisation; it does not publish the app or activate a
scenario.
In the module's **Connection** field, choose **Add**. Make opens Perkstar's
hosted authorisation page over HTTPS.
Check the business and signed-in account shown by Perkstar. If either is
wrong, cancel and switch Perkstar organisation before approving. Do not
authorise first and rely on a later module filter to isolate another
business.
Read the plain-language permissions and choose **Allow** only if they match
the intended scenario. The private-beta app requests customer, enrolment,
card, event, webhook, marketplace-loyalty, and Wallet-push permissions used
by its guided modules. If the connection offers **Advanced API scopes**,
leave them unselected unless a documented **Make an API call** operation
requires one; each selected scope appears on the Perkstar consent screen.
Perkstar returns the connection to Make without displaying an API key.
Use a name that identifies the tenant, for example `Perkstar — North Street
Coffee (Live)`. Open the module again and confirm card selectors and a safe
search return data only from that business.
The Make OAuth client allows five optional advanced scopes for documented
enrolment writes, transaction reads/writes, app-owned webhook reads, and
location reads. They are not part of an ordinary guided connection. Read
[OAuth permissions](/integrations/make/data-security#oauth-permissions) before
requesting one. Adding a scope later requires renewed consent; Make cannot add
it silently to an existing grant.
## Test a read-only scenario first
Select **Search customers**, choose the new connection, and use an
authorised internal test customer's exact email, phone, external reference,
or pass barcode/serial. You can also filter by **Created after**. Use a
narrow Limit for this connection test; Customer ID is not an input to this
search module.
Choose **Run once** in Make. Open the module's output bundle and confirm the
customer ID and business-owned fields are the expected record. A no-match
result is not permission to guess another tenant's identifier.
Map only the fields a low-risk destination step needs. Keep the scenario
inactive until its filters, error handler, access, and data retention have
been reviewed.
## Test the instant trigger
Add **Watch loyalty events** as the first module, create its attached
webhook, and select one event. Choose a Card only when that event carries a
Card ID and the scenario belongs to a single programme. Leave test events
excluded unless this is an isolated test scenario.
Choose **Run once**, then perform the exact low-risk event in the connected
Perkstar business. A generic `webhook.test` diagnostic does not satisfy the
module's business-event selection.
Confirm the trigger's authenticated Perkstar verification request succeeded,
then inspect the stable outer Event ID, dotted Event Type, Created
timestamp, Organization ID, and nested Event Data before mapping another
module. Optional Event Data fields can be absent or `null`.
Add filters and an error handler, save the scenario, then schedule it **On**
for one event/card and a narrow audience. Monitor Make scenario history,
incomplete executions, and the corresponding Perkstar records before
widening it.
## Connection and webhook lifecycle
| Change | Effect |
| - | - |
| Rename a connection | Changes its Make label only; the OAuth grant remains bound to the same Perkstar business. |
| Reauthorise a connection | Future modules use the renewed OAuth grant. Retest every active scenario that uses it. |
| Revoke access in Perkstar | Future API calls fail and app-owned subscriptions can no longer be managed until a valid connection is restored. |
| Turn a scenario off | Stops normal scenario processing, but does not necessarily delete its attached Make webhook. Check the scenario and Make webhook queue before assuming the Perkstar subscription is gone. |
| Delete the attached webhook | The app's detach step deletes the corresponding app-managed Perkstar subscription. Historical Make executions remain under Make's retention settings. |
| Delete a destination connection | Does not remove records the scenario already copied into that destination. |
To revoke Perkstar access, open **Settings → Authorised apps** in the connected
Perkstar business and revoke the Make connection. Then remove or reauthorise the
connection in Make before reactivating affected scenarios.
Read [Webhooks and instant scenarios](/integrations/make/webhooks) before using
an event trigger, [Troubleshooting](/integrations/make/troubleshooting) before
reconnecting a shared production connection, and [Data and
security](/integrations/make/data-security) before mapping personal data.
# Make troubleshooting
Source: https://developers.perkstar.co.uk/integrations/make/troubleshooting
Diagnose private-beta access, OAuth, instant triggers, modules, queues, retries, rate limits, and consent failures.
Start with the scenario's execution history, incomplete executions, and the
connected Perkstar business. Record the module name, UTC time, status/code, and
Perkstar `X-Request-Id` before retrying. Never copy an OAuth token, Make webhook
URL, or full customer bundle into a support message.
## Access and connection
The app is a private beta and is not publicly searchable in Make's app
catalogue. Confirm that Perkstar enabled the Make organisation you are
currently using. An eligible Perkstar plan alone does not grant beta access.
Make access requires Growth, Scale, Enterprise, or Franchise. Check the
current plan and that OAuth is opening the intended business. Free and
Starter businesses cannot connect the integration.
Cancel instead of approving. Switch to the correct Perkstar organisation,
then add a new connection. A later Make filter cannot change the tenant
bound to an OAuth grant.
Reopen the module and select the newly created connection explicitly. Make
connections belong to a team context; confirm the scenario is in the team
where the connection was created and that your Make role can use it.
Reauthorise it once, then run a read-only **Search customers** test. If
Perkstar access was revoked, a new consent is required; retrying the old
execution cannot restore the grant. Retest every active scenario sharing
that connection.
## Watch loyalty events
Start **Run once** before performing the event. Confirm the module selected
the exact dotted business event, correct Perkstar connection, and correct
Card when a Card filter is set. The generic `webhook.test` diagnostic is not
one of the module's 29 event choices.
Confirm the scenario is saved and On, its attached webhook still exists, the
OAuth connection is authorised, and the business operation actually reached
a completed state. Inspect Make's webhook queue, execution history, and
incomplete executions. If no bundle exists, report the event ID and UTC time
to Perkstar support without sharing the callback URL.
Turning a scenario Off does not necessarily delete its attached webhook.
Make can retain webhook state or queued bundles depending on configuration.
Inspect timestamps and the webhook queue before processing; delete the
attached webhook if the upstream subscription should end.
Perkstar delivery is at least once. Compare the stable event ID. Add a
uniqueness check or Make Data Store guard before a non-idempotent
destination write, and use the same ID as the downstream source reference.
This is allowed. Compare Event Data `occurredAt` or the outer Created value
and the current destination state. Do not order business changes by Make
execution time.
Event bundles are not enriched with a full customer profile, and optional
fields do not apply to every occurrence. Review the [event
catalogue](/reference/webhook-events), guard mappings, and add **Search
customers**, **Search enrolments or passes**, or a documented read through
**Make an API call** only when current state is appropriate.
Creating a pass or opening a save link is not installation evidence. Apple
normally reports a device registration. Google is observed periodically;
provider response, object age, and projector backlog can extend the delay. A
business's first Google subscription uses a completed sweep as a no-event
baseline, so enable and test before distributing install links.
**Card Scanned** covers successful online Perkstar Scanner lookups only. A
cache-only offline scan, dashboard search, or POS customer lookup does not
cross the webhook boundary.
The event reports movement among Perkstar's six lifecycle groups, not entry
into a saved segment. Initial classification is stored as a no-event
baseline to avoid replaying the customer base.
## Searches and actions
| Symptom | Likely cause | What to do |
| - | - | - |
| Search customers returns no bundle | Exact email, phone, external reference, pass serial, or Created after filter does not match | Correct or remove the filter and keep a narrow Limit. Use `GET /customers/{id}` for a known Customer ID. |
| Search enrolments or passes has no Wallet URL | Pass issuance is pending, filters do not match, or that Wallet platform is not configured | Check Customer ID, Card, and Status; retry later and never construct an install URL. |
| Find or Enrol reports inactive/revoked | That customer/card pair exists and Perkstar will not silently undo its status | Review and explicitly reactivate it in Perkstar; do not create a duplicate customer. |
| A Card is absent from a focused module | The card is inactive or its type is incompatible | Choose the matching module/card type. Manually mapped incompatible IDs are rejected too. |
| `400 ambiguous_default_card` | Several active cards exist and none was selected | Select the intended Card explicitly. |
| `401` or connection error | OAuth grant is invalid, expired beyond refresh, or revoked | Reauthorise, run a read-only test, then retest every affected scenario. |
| `403` permission error | Grant lacks the operation's scope, plan/role is ineligible, or the operation is forbidden | Reauthorise the official connection and confirm plan/role. Never substitute a raw API key. |
| `403 push_marketing_consent_required` | Customer lacks Wallet push-marketing consent | Stop the message and follow the approved consent process; do not route around it. |
| `404` | Customer, enrolment, card, or transaction is not in this business or no longer exists | Check the connection and opaque IDs; do not reuse an ID from another tenant. |
| `409` creating a customer | A conflicting customer exists and no stable external-reference upsert was used | Find the existing customer or use the source system's genuine stable external reference. |
| `409 external_transaction_id_conflict` | A source ID was reused with different customer, card, operation, or amount | Keep original inputs for a retry, or use the different source record's own ID. |
| `409 webhook_subscription_limit_reached` | This Make app, installing Perkstar user, and business share 200 subscriptions, including paused rows | Remove unused Make webhooks, confirm detach, then create the new webhook again. |
| `422` loyalty validation | Activity/amount does not match the Card type, or a source reference belongs to the other environment | Correct the mapping. Do not hide the error by generating a new source ID. |
| `429` | API limit or three-minute Wallet-push card cooldown | Honour `Retry-After`; reduce iterators, concurrency, and bursts. |
| `5xx` or network timeout | Temporary Perkstar or network failure | Retry the same logical operation with unchanged stable IDs; check [API status](/support/status). |
## Make an API call
| Symptom | What to check |
| - | - |
| Invalid or unsupported URL | Use a relative public v1 path such as `/customers/{id}`. Do not pass a full host or private dashboard path. |
| Missing authentication | Select the Perkstar connection. The module supplies OAuth and has no arbitrary-header input. |
| Duplicate POST after retry | Map the same stable value (up to 255 characters) into **Idempotency Key** on every attempt and inspect whether the first call succeeded. |
| Guided module succeeds but universal call returns `403` | The connection did not grant the required optional permission, or the operation is not available to that business or scope. |
| Response body does not match a mapping | Confirm the current public API schema and guard optional fields; do not assume a dashboard response shape. |
## Incomplete executions and safe replay
Before resolving or replaying an incomplete Make execution:
1. Decide whether the earlier Perkstar or destination module may already have
succeeded.
2. Preserve the original source event, order, payment, activity, or request ID,
and keep every mapped field that contributes to the request fingerprint
unchanged—including customer identity, Card, activity type, amount, note,
metadata, and any create-if-missing fields.
3. Fix non-retryable validation, permission, consent, or conflict errors first.
4. Retry the failed path once and inspect the returned Perkstar record.
5. Confirm no iterator/router path can execute the same write again with a new
source ID.
To reverse a loyalty write, prefer its returned Perkstar Transaction ID. If only
the upstream source ID is available, use the exact original reference and
operation expected by **Reverse a loyalty transaction**.
## Webhook attestation failure
The official trigger sends the received event and signed headers back to
Perkstar over OAuth before it outputs a normal bundle. If that check fails, do
not map around it: confirm the attached webhook still belongs to the selected
connection, the event was not altered, the execution is recent, and the
Perkstar business and OAuth grant remain active. Keep the callback URL secret.
A temporary verifier outage can leave a Make execution failed or incomplete
after its callback was already acknowledged. Resume the same execution after
service recovers and preserve the original Event ID. Exact proofs remain
recoverable for up to 90 days; older proofs fail closed. See [Webhooks and
instant scenarios](/integrations/make/webhooks).
## Ask for help
Email [support@perkstar.co.uk](mailto:support@perkstar.co.uk) with:
* the Perkstar business name;
* the Make organisation/team and scenario name (not a private link);
* the Perkstar module and approximate UTC time;
* the Make execution ID and Perkstar `X-Request-Id`, event ID, or delivery ID
when available; and
* the status/error code with secrets and personal fields removed.
For suspected credential exposure or a personal-data incident, contact
[privacy@perkstar.co.uk](mailto:privacy@perkstar.co.uk) immediately.
# Webhooks and instant scenarios
Source: https://developers.perkstar.co.uk/integrations/make/webhooks
Understand Make attached webhooks, server-attested delivery verification, retries, duplicate protection, and queues.
**Watch loyalty events** is an instant trigger backed by a Make attached
webhook. When its webhook is created, the app registers the unique Make HTTPS
callback with Perkstar for one event and optional Card/live-test filters.
Perkstar sends matching events as they happen; the module does not poll customer
or transaction lists.
Let the official module create and manage its subscription. Do not also copy a
custom Make webhook URL into Perkstar for the same event unless two
independent deliveries are an intentional, reviewed design.
## Attached webhook lifecycle
The module sends one create request containing Make's unique HTTPS callback,
the selected event and filters, and active state. Perkstar returns the
subscription ID that Make stores for detach; there is no separate activation
request. A retried create uses the same deterministic callback identity to
recover the live row instead of creating another subscription.
Perkstar durably creates a delivery before scheduling the outbound POST.
Events that do not match the event type, Card, or live/test selection are
rejected before an outbound delivery is created.
An HTTP `2xx` acknowledges the delivery. Acceptance by Make proves only that
its webhook endpoint received the bundle; inspect scenario history and
incomplete executions to confirm downstream modules completed.
Deleting the attached webhook invokes the app's detach operation and deletes
that app-owned Perkstar subscription. Recreating it produces a new callback
relationship. Scenario and destination history are not erased.
Turning a scenario **Off** and deleting its attached webhook are different
operations. Do not assume an inactive scenario has already removed the
Perkstar subscription. Check the scenario's webhook configuration and Make's
webhook queue, then delete an unused attached webhook deliberately.
One Perkstar OAuth application, installing Perkstar user, and business
combination can own up to 200 Perkstar webhook subscriptions. Multiple Make
connections authorised by that same Perkstar user for that business share the
allowance. Paused rows left by interrupted cleanup or a revoked grant still
count, and each **Watch loyalty events** webhook normally uses one. At the
limit, remove unused attached webhooks and confirm detach succeeded; Perkstar returns
`409 webhook_subscription_limit_reached` rather than replacing another
scenario's subscription.
Perkstar binds subscription idempotency to the live row rather than a short
response cache. A lost create response, access-token refresh, or repeated
attach call with the same app identity can recover that row. Deleting it
releases the identity and capacity immediately.
The first Customer Lifecycle Group Changed or Google Wallet Pass Installed
subscription for a business needs one completed warm-up sweep. Perkstar stores
existing state without replaying the customer base, then tracks later changes.
Apple installation remains callback-driven.
## Event identity
Perkstar sends this common envelope:
```json theme={null}
{
"id": "whd_01JEXAMPLE",
"type": "transaction.created",
"created": 1785312000,
"orgId": "org_123",
"data": {
"enrollmentId": "enr_123",
"type": "STAMP",
"delta": 1,
"occurredAt": "2026-08-02T10:00:00.000Z"
}
}
```
`id` and `X-Perkstar-Delivery-Id` identify one logical delivery and stay stable
across automatic retries. `created` is the source event's `data.occurredAt`
expressed as Unix seconds, not the delivery-attempt time. Different events can
arrive out of order.
Use the event ID as the scenario's duplicate key. If a destination write is
not naturally idempotent, record processed IDs in a destination uniqueness
constraint or a Make Data Store before the write. Do not assume Make will
deduplicate two accepted deliveries automatically.
## Delivery policy
| Attempt | Timing |
| - | - |
| 1 | Immediately |
| 2 | 1 minute after the first failure |
| 3 | 5 minutes after the second failure |
| 4 | 30 minutes after the third failure |
* Any HTTP `2xx` response succeeds.
* A non-`2xx`, network failure, or response taking longer than ten seconds
schedules the next attempt.
* `410 Gone` permanently exhausts that delivery and pauses the Perkstar
subscription.
* After four failed attempts, the delivery is exhausted and retained for
support diagnostics.
* Delivery is at least once. Every route and destination write must tolerate a
duplicate.
* Perkstar retries only when delivery to Make fails. If Make accepted the
bundle and a later scenario module failed, resume or retry the Make execution
with the same source identifiers.
* Use `data.occurredAt` or outer `created` for business ordering, not arrival
time or Make execution time.
## Server-attested delivery verification
Perkstar signs every outbound request with HMAC-SHA256 and sends
`X-Perkstar-Signature: t=,v1=`. Make exposes the parsed JSON
event to a custom app rather than the exact original bytes, so the official
module does not attempt to recreate the raw-body HMAC inside Make.
Instead, **Watch loyalty events** sends the received event and signed delivery
headers back to Perkstar over the tenant-scoped OAuth connection before it
outputs a bundle. Perkstar verifies the app-owned subscription, organisation,
authorising user, delivery ID, signing time, stored signature proof, and exact
event envelope. A missing, stale, forged, cross-tenant, or altered delivery is
rejected and does not become a normal scenario bundle. The per-subscription
signing secret remains encrypted in Perkstar and is never stored by Make.
Treat the callback URL as a secret as an additional defence: never log it,
paste it into a ticket, expose it in a screenshot, or reuse it as a public
endpoint. The stable event ID remains the duplicate key; verification proves
origin and integrity but does not turn at-least-once delivery into exactly-once
processing.
Make acknowledges the incoming HTTP delivery before the scenario's
authenticated verification step finishes. A temporary Perkstar verification
outage therefore appears in Make as a failed or incomplete execution rather
than causing Perkstar to resend an already accepted callback. Resume that
execution with the same event ID after service recovers. The exact stored
proof remains recoverable for up to 90 days, matching Perkstar's terminal
webhook-delivery retention; proofs older than that are rejected. Normal
duplicate handling by Event ID is still required when an execution is resumed
or replayed.
## Test an instant scenario
1. Add **Watch loyalty events** as the first module.
2. Select the intended Perkstar connection and create its attached webhook.
3. Choose exactly one Event and, only when that event carries a Card ID, the
intended Card.
4. Keep **Include Test Events** off for a live scenario.
5. Choose **Run once**, then perform the exact event in Perkstar.
6. Confirm the module completed its Perkstar verification request, then inspect
the event ID, event type, organisation, source time, and relevant fields
inside **Event Data** before mapping another module.
7. Stop **Run once**, add duplicate/error handling, save, and turn the scenario
on only after the test result is understood.
The `webhook.test` diagnostic is not an Event choice. A sample bundle is not a
promise that every optional field will be populated on later events.
## Observation boundaries
* **Wallet Pass Installed** fires on first provider-owned installation
evidence. Apple reports device registration directly. Recently issued Google
passes are eligible for a periodic projector; object age, provider response,
and backlog can extend the delay. Issuing a pass or opening a save link is not
installation evidence.
* **Card Scanned** covers successful online Perkstar Scanner lookups only. An
offline cache lookup, dashboard search, or POS lookup is outside the event.
* **Customer Card Expired** belongs to one enrolment and effective expiry. If
an extension later reaches a new expiry, another event is expected.
* **Customer Lifecycle Group Changed** tracks movement among six Perkstar
lifecycle groups, not saved-segment membership. Initial classification is a
suppressed baseline.
* **New Customer Referral** is one loyalty customer referring another. It
is not a merchant, agency, partner, or affiliate invitation.
Some bundles contain purchaser or customer data. Make execution history,
queues, Data Stores, and every mapped destination can retain those values. Read
[Data and security](/integrations/make/data-security) before activating the
scenario.
# Meta Pixel
Source: https://developers.perkstar.co.uk/integrations/meta-pixel/index
Configure Meta Pixel measurement for supported customer journeys.
Send supported customer journey events to your business's Meta Pixel account. This
is measurement, not a loyalty balance source or proof that a message was delivered.
## Configure the connection
1. Select the intended business in **Perkstar → Integrations → Meta Pixel → Connect**.
2. Enter the **Pixel ID** and **Conversions API token** from the property or data source you
control in Meta Events Manager.
3. Save in the integration workspace. These are business-level settings inherited
by its cards; do not paste a different business's credentials into a card.
4. A saved-secret hint means the secret is already stored. Leaving it untouched
preserves it; entering a replacement deliberately updates it.
## Check an event
Use a controlled test customer and a supported enrolment or loyalty journey with
the required recorded marketing consent. Inspect the matching event in Meta Events Manager.
The implementation requires both the identifier and secret, plus the applicable
consent, before firing these events. A saved identifier alone is not a completed
verification.
## Troubleshooting and ownership
Check the correct business, identifier, saved secret and test customer's consent.
Provider reporting can differ from Perkstar transaction totals; attribution events
are not the accounting record. Do not remove consent requirements to make a test
appear. Keep secrets private and rotate them through the provider when necessary.
Use the available workspace controls to remove the configuration when retiring it,
then confirm with a controlled test that no new event is generated.
See [security and privacy](/fundamentals/security-privacy).
# Mindbody
Source: https://developers.perkstar.co.uk/integrations/mindbody/index
Availability and next steps for Mindbody.
**Not open for new connections.** Reviewed 13 September 2026. The status shown
in the intended business's dashboard is authoritative for that account.
Connect a studio to reward eligible class and appointment attendance. The current workspace does not offer general self-service setup for this provider.
## What to do now
Open **Perkstar → Integrations** and inspect Mindbody. If it says **Coming soon**
or **Unavailable**, do not use an old setup URL or grant provider credentials to
work around it. Documentation and a provider's developer portal do not themselves
grant access to a Perkstar connector.
If you already have an approved connection, use **My integrations → Manage** where
available. Keep the original provider account and transaction references when
asking support about a failure. Do not disconnect a working installation merely
to test whether you can reconnect it.
## Discuss compatibility with support
Provide the business account number, provider product/version, country, relevant
store or location, and the loyalty workflow you need. Do not share passwords,
API keys or customer lists. Ask support to confirm both access and an appropriate
controlled test before relying on this connection for customer transactions.
For a bespoke connection, start with the [POS guide](/guides/pos) and
[API availability](/support/api-availability). A custom integration is a separate
implementation, not a way to enable an unreleased native connector.
# MX POS
Source: https://developers.perkstar.co.uk/integrations/mx-pos/index
Availability and next steps for MX POS.
**Not open for new connections.** Reviewed 13 September 2026. The status shown
in the intended business's dashboard is authoritative for that account.
Configure MX POS transaction polling and card routing when the connector is released. The current workspace does not offer general self-service setup for this provider.
## What to do now
Open **Perkstar → Integrations** and inspect MX POS. If it says **Coming soon**
or **Unavailable**, do not use an old setup URL or grant provider credentials to
work around it. Documentation and a provider's developer portal do not themselves
grant access to a Perkstar connector.
If you already have an approved connection, use **My integrations → Manage** where
available. Keep the original provider account and transaction references when
asking support about a failure. Do not disconnect a working installation merely
to test whether you can reconnect it.
## Discuss compatibility with support
Provide the business account number, provider product/version, country, relevant
store or location, and the loyalty workflow you need. Do not share passwords,
API keys or customer lists. Ask support to confirm both access and an appropriate
controlled test before relying on this connection for customer transactions.
For a bespoke connection, start with the [POS guide](/guides/pos) and
[API availability](/support/api-availability). A custom integration is a separate
implementation, not a way to enable an unreleased native connector.
# PAX
Source: https://developers.perkstar.co.uk/integrations/pax/index
Availability and next steps for PAX.
**Unavailable.** Reviewed 13 September 2026. The status shown in the intended
business's dashboard is authoritative for that account.
PAXSTORE manages terminal fleets but does not provide the transaction feed this Perkstar connection needs. This is not a supported way to connect PAX sales to loyalty.
## What to do now
Open **Perkstar → Integrations** and inspect PAX. If it says **Coming soon**
or **Unavailable**, do not use an old setup URL or grant provider credentials to
work around it. Documentation and a provider's developer portal do not themselves
grant access to a Perkstar connector.
If you already have an approved connection, use **My integrations → Manage** where
available. Keep the original provider account and transaction references when
asking support about a failure. Do not disconnect a working installation merely
to test whether you can reconnect it.
## Discuss compatibility with support
Provide the business account number, provider product/version, country, relevant
store or location, and the loyalty workflow you need. Do not share passwords,
API keys or customer lists. Ask support to confirm both access and an appropriate
controlled test before relying on this connection for customer transactions.
For a bespoke connection, start with the [POS guide](/guides/pos) and
[API availability](/support/api-availability). A custom integration is a separate
implementation, not a way to enable an unreleased native connector.
# GoDaddy Poynt
Source: https://developers.perkstar.co.uk/integrations/poynt/index
Availability and next steps for GoDaddy Poynt.
**Not open for new connections.** Reviewed 13 September 2026. The status shown
in the intended business's dashboard is authoritative for that account.
Configure a Poynt business for sales polling and customer matching when released. The current workspace does not offer general self-service setup for this provider.
## What to do now
Open **Perkstar → Integrations** and inspect GoDaddy Poynt. If it says **Coming soon**
or **Unavailable**, do not use an old setup URL or grant provider credentials to
work around it. Documentation and a provider's developer portal do not themselves
grant access to a Perkstar connector.
If you already have an approved connection, use **My integrations → Manage** where
available. Keep the original provider account and transaction references when
asking support about a failure. Do not disconnect a working installation merely
to test whether you can reconnect it.
## Discuss compatibility with support
Provide the business account number, provider product/version, country, relevant
store or location, and the loyalty workflow you need. Do not share passwords,
API keys or customer lists. Ask support to confirm both access and an appropriate
controlled test before relying on this connection for customer transactions.
For a bespoke connection, start with the [POS guide](/guides/pos) and
[API availability](/support/api-availability). A custom integration is a separate
implementation, not a way to enable an unreleased native connector.
# Delivery reports and recovery
Source: https://developers.perkstar.co.uk/integrations/resend/delivery-recovery
Understand email outcomes and recover a stopped or failed send without changing sending accounts silently.
## Read the campaign report
Open **Invitation campaigns**, choose the campaign and check which sending account
the run used. A connection status and an individual message outcome answer different questions.
| Outcome | What it means |
| - | - |
| Queued or waiting | Delivery has not finished; the next check time is not a delivery promise |
| Excluded or held before sending | The address was not submitted. A quality verdict is not a bounce |
| Provider accepted | Resend accepted the request; it does not prove inbox placement or reading |
| Delivered | Resend reported delivery; it does not prove reading |
| Bounced or failed | The provider reported rejection or failure; inspect its reason |
| Uncertain | Perkstar cannot safely establish the outcome yet; do not assume it is unsent |
A later bounce can follow an earlier accepted or delivered event. Read the outcome
and provider evidence together rather than adding every historical status as a
separate recipient.
## Retry deliberately
Connecting Resend does not restart a stopped campaign. Review the remaining
recipients and the selected sending account before choosing a supported retry.
Previously accepted invitations and uncertain deliveries retain their original
provider record; changing accounts is not a way to resend them automatically.
Consent, unsubscribe and duplicate protection remain enforced.
When using your own Resend account, Perkstar does not buy an Emailable check or
apply its shared address-quality verdicts and bounce-rate pauses. Your own Resend
account can still suppress an address, exhaust a quota or reject a message under
its policies. A Perkstar suspension or unrelated abuse restriction still applies.
## Disconnect or replace the account
Open **Integrations → Resend → Manage Resend** and choose **Disconnect Resend**.
This stops use of the saved sending key. It does not recall accepted emails.
Sending remains unavailable until a replacement connection is explicitly activated;
Perkstar does not silently switch these messages to its shared sender.
You can also revoke the named Perkstar key and remove its webhook in Resend.
Removing the webhook stops later delivery updates. Retain the relevant records
while reconciling any pending or uncertain messages.
## What to give support
Business account number, campaign name or reference, the approximate time, selected
sender, visible error and the provider's message ID if available. Do not include
API keys, webhook secrets or a full customer list.
See [connection setup](/integrations/resend/setup) and the
[email sending terms](https://dashboard.perkstar.co.uk/email-provider-terms).
# Resend
Source: https://developers.perkstar.co.uk/integrations/resend/index
Connect your own sending account, verify delivery and manage customer invitation emails.
Send supported customer invitations and card-install links using your own
Resend account and verified domain. Manage the connection inside **Perkstar →
Integrations → Resend**. This is a business integration; white-label ownership is
not required.
Prepare your domain, connect, test delivery and choose when to activate.
Check what was accepted, delivered, held or bounced, and recover without
duplicating invitations.
## Choose a sending account
| | Perkstar's shared service | Your connected Resend account |
| - | - | - |
| Sending account and domain | Perkstar's | Yours |
| Emailable address checks | Applied to supported shared sending | Not used; no Perkstar verification credits spent |
| Shared quality exclusions and bounce-rate pauses | Apply | Do not apply |
| Shared invitation allowance | Applies | Does not apply; your provider quotas and other feature entitlements remain |
| Consent, unsubscribe and duplicate protection | Retained | Retained |
| Provider fees and restrictions | Perkstar's service rules | Your Resend contract and quotas |
| Connection failure | Reported or held | Held or failed; never silently sent through Perkstar |
## What uses this connection
Initial invitations, invitation follow-ups and supported customer card-install
emails, including install links for imported customers. Importing a customer
record alone does not send an email or prove permission to contact that person.
Perkstar sign-in, security and billing emails remain separate. Connecting Resend
does not enable the retired manual marketing email composer, send SMS, or
configure Klaviyo flows.
## Before you start
You need the business owner's own Perkstar login, email-feature access, a Resend
account and a verified sending domain. A staff login or Perkstar support preview
cannot connect it on your behalf. A closed or suspended account remains blocked.
Resend can independently reject, suppress or limit mail from your account.
Read the [email sending and connection terms](https://dashboard.perkstar.co.uk/email-provider-terms).
Activation is an explicit choice after a signed delivery test. It does not
restart a stopped campaign or resend previously accepted invitations.
# Connect your Resend account
Source: https://developers.perkstar.co.uk/integrations/resend/setup
Set up a verified domain and activate email sending inside Perkstar's integrations workspace.
The complete flow stays in **Integrations → Resend → Connect Resend**. Its progress
steps are **Prepare → Connect → Test delivery → Activate**.
## Have these details ready
| Field in Perkstar | What to enter |
| - | - |
| Sending email address | An address on the exact domain verified for sending in your Resend account, such as `loyalty@mail.example.com` |
| Reply-to email address | The mailbox where your team receives customer replies |
| Verified Resend domain ID | The ID of that verified domain in Resend, not the domain name |
| Temporary full-access setup key | A Resend API key that can inspect the domain and create the connection resources |
Use your own domain and mailbox. Do not enter a Perkstar domain, a password or a
key belonging to a different business. A domain and its subdomain are different:
verifying `example.com` does not satisfy an exact sender check for `mail.example.com`.
In your [Resend account](https://resend.com/domains), add the domain you
own, follow its DNS instructions and wait until it is verified with sending
enabled. Copy its domain ID. Domain verification is completed in Resend;
Perkstar does not modify your DNS records.
Open [Resend API keys](https://resend.com/api-keys) and create a full-access
key for setup. Keep it private. Perkstar uses it to create a separate
sending-only key restricted to the verified domain and a signed delivery
webhook. Perkstar does not store the temporary full-access key.
Sign in as the business owner and confirm the correct business. Open
**Integrations → Resend → Connect Resend**, enter the four details and read
the connection terms. Tick the acknowledgement, then choose **Connect and
test Resend**. This creates the connection resources; it does not activate
customer sending.
The test goes only to Resend's `delivered@resend.dev` test address. No
customer receives it. Choose **Refresh status** while waiting. The
connection must reach **Test passed — ready to activate** before you can
continue. Provider acceptance alone is not enough: Perkstar requires the
signed delivery event for this test.
Choose **Use my Resend account**. Confirm that the current sending account
now shows your Resend sender. You can revoke the temporary full-access setup
key in Resend; retain the named Perkstar sending key and webhook while using
the integration.
## Check the result
* **Manage Resend** still appears inside the integration workspace.
* The selected sending account shows your sender and the connection is connected.
* A saved connection is not a guarantee that every future email will be delivered.
* No stopped campaign has restarted automatically. Review the campaign separately
before deliberately choosing a new send or retry.
## If setup does not finish
| What you see | What to check |
| - | - |
| Domain not verified or inaccessible | Exact sender domain, sending-enabled status, domain ID and access of the temporary setup key |
| Waiting for signed delivery confirmation | Refresh status; check the test email and webhook delivery in Resend. Do not activate based only on an accepted event |
| Setup needs attention | Read the error. Correct the provider configuration, disconnect the failed connection and reconnect |
| Only the owner can manage | Use the actual owner's login, outside a support or impersonation session |
| Existing connection | Inspect its status first. Disconnect deliberately before replacing it |
Do not post API keys or webhook secrets in screenshots, support messages or shared
documents. For a failed test, provide the business account number, time and visible
error instead. Continue with [delivery and recovery](/integrations/resend/delivery-recovery).
# Setmore
Source: https://developers.perkstar.co.uk/integrations/setmore/index
Availability and next steps for Setmore.
**Not open for new connections.** Reviewed 13 September 2026. The status shown
in the intended business's dashboard is authoritative for that account.
Sync appointments and credit the customer's wallet after attendance. The current workspace does not offer general self-service setup for this provider.
## What to do now
Open **Perkstar → Integrations** and inspect Setmore. If it says **Coming soon**
or **Unavailable**, do not use an old setup URL or grant provider credentials to
work around it. Documentation and a provider's developer portal do not themselves
grant access to a Perkstar connector.
If you already have an approved connection, use **My integrations → Manage** where
available. Keep the original provider account and transaction references when
asking support about a failure. Do not disconnect a working installation merely
to test whether you can reconnect it.
## Discuss compatibility with support
Provide the business account number, provider product/version, country, relevant
store or location, and the loyalty workflow you need. Do not share passwords,
API keys or customer lists. Ask support to confirm both access and an appropriate
controlled test before relying on this connection for customer transactions.
For a bespoke connection, start with the [POS guide](/guides/pos) and
[API availability](/support/api-availability). A custom integration is a separate
implementation, not a way to enable an unreleased native connector.
# Shopify
Source: https://developers.perkstar.co.uk/integrations/shopify/index
Connect the intended store and verify order, location and loyalty routing.
Reward eligible online and POS orders with customer matching, order reconciliation
and refund recovery. Availability is beta and depends on configuration and the
business's integration entitlement.
## Connect and choose the store
1. Open the intended business in **Perkstar → Integrations → Shopify**.
2. Choose **Connect** and enter the store details requested by the setup form.
3. Review Shopify's authorisation for the correct store. If Perkstar asks you to
choose a business, select it explicitly before continuing.
4. Return to **Manage** and confirm the store account. Review the default programme
and location routes before processing customer sales.
Do not connect a second store simply to bypass a missing permission or failed
setup. Each store's programme and location choices should reflect the business's
actual checkout process.
## Check one controlled order
Use an authorised test customer who can be matched to the intended programme.
Check the eligible paid order, its source reference, Perkstar loyalty transaction
and reporting location. Follow a controlled refund through the same records.
Repeated source events must not become repeated loyalty credits.
A connected store or recent product catalogue sync does not prove that a particular
order qualified for loyalty. Check order processing and customer matching separately.
## Recover and disconnect
Use the workspace's activity and error details to identify the affected store,
order and location. Fix mapping or authorisation before requesting supported
recovery. Do not manually credit and replay the same sale without reconciling it.
Disconnect in **Manage** when retiring the connection, and confirm any remaining
Shopify app installation or separately configured automations in Shopify.
For custom integrations, see [customer sync](/guides/customer-sync) and
[idempotency](/fundamentals/idempotency).
# Earn with Square and redeem in Perkstar
Source: https://developers.perkstar.co.uk/integrations/square/earning-redemption
Attach an existing Square Customer, award the routed Perkstar programme and understand the separate Perkstar redemption boundary.
Square provides the completed sale and refund signals. Perkstar owns the member,
loyalty balance, Wallet pass and reward redemption.
A seller can start earning through Square's standard customer-attachment path.
Wallet QR identification is optional. Customers can redeem eligible rewards
themselves from their pass, or staff can use Perkstar Scanner. Neither path
requires Square Loyalty or a Square QR scanner.
## Award a completed payment
### Standard customer attachment
The customer joins the business's Perkstar programme before their first
eligible Square sale. Adding the pass to Apple Wallet or Google Wallet lets
them view updates and present the card; installation is not required for
email or phone matching to an active enrolment.
Use Square's normal customer search and choose the existing Square Customer
whose email address or phone number exactly matches the Perkstar member. If
both fields are present, their exact matches must identify the same member.
Confirm the intended Square Customer is attached to the sale before taking
payment. Perkstar does not guess the buyer of an anonymous sale.
Perkstar reads the completed Square payment, follows the location's
programme route, credits the existing member once and queues their Wallet
pass update.
### Optional Wallet QR attachment
On a tested compatible device, staff can replace the normal customer search
with one Wallet QR scan. The business must first enable Wallet-card
identification, and that customer must have given current consent.
In the Square checkout, open **Review sale → Add customer → scan icon**.
Scan the QR code on the customer's Perkstar Wallet pass and confirm the
correct Square Customer is attached before payment. Perkstar either reused
one complete exact match or, only if none existed, created the profile.
The payment follows the same customer-attributed earning path as a customer
attached through Square's standard search.
Wallet QR compatibility depends on the Square app and device. Terminal or
Register running Square Point of Sale needs both **Scan customers using device
camera** and **Show Add customer button during checkout** enabled. Attaching a
customer only after checkout is not sufficient for Perkstar earning. Keep
Square for Retail or Restaurants current. Test a Handheld or physical scanner
against a QR displayed on a phone before relying on it; otherwise use the
standard Square customer search.
A customer must already belong to the routed Perkstar programme. An anonymous
payment does not earn. The optional Wallet QR path does not change the payment
boundary: an unrelated attached Square customer who does not match an existing
Perkstar member is not enrolled, and the unmatched contact is not retained.
## How earning is calculated
| Programme | Square payment result |
| - | - |
| Ordinary Stamp | One stamp for the completed customer-attributed payment |
| Spend-based Stamp | Whole thresholds met × stamps configured per threshold |
| Visit-based Stamp | The configured stamps per visit |
| Spend-based Points | The configured points rate applied to the paid amount |
| Visit-based Points | The configured points per visit |
| Cashback | The active tier's percentage applied to the paid amount |
The Square location either inherits the merchant's explicit default programme,
uses its configured override, or deliberately pauses loyalty. Payment and
webhook redelivery are idempotent, so the same completed payment cannot credit
twice.
### Amount, timing and limits
* Spend earning uses Square's `Payment.amount_money`, excluding the separately
reported staff tip. It is not a pre-tax subtotal: Perkstar does not inspect
individual products, tax lines or category exclusions. See Square's
[Payment definition](https://developer.squareup.com/reference/square/objects/Payment).
* Square and the Perkstar business must use the same currency. There is no
currency conversion. Spend-points rates include the programme's configured
spend unit and are rounded to two decimal places; spend-stamp thresholds are
rounded down. Cashback is stored in whole minor currency units.
* The earning unit is a **payment**, not an order or a calendar-day visit.
Split-tender payments can produce more than one visit award; spend-stamp
thresholds are evaluated separately for each payment. Do not promote
one-award-per-basket or combined split-tender thresholds.
* Processing is asynchronous: Square notifications are persisted, then the
background worker and Wallet updates run. A Connected badge is not proof
of a sale being credited. Offline sales cannot earn before Square receives
the payment and Perkstar processes it.
* Cancelled, failed, zero-value and anonymous payments do not earn. This
integration follows payment completion, not appointment attendance or
no-show status. It does not import historical sales from before installation.
Programme rewards, daily stamp limits and applicable promotion rules remain
Perkstar rules. Confirm the exact merchant programme, expected amount and
reward threshold in the final test; do not infer them from the Square basket.
## Redeem a reward
Redemption is completed in Perkstar. **Square Loyalty is not required**, and
rewards are not copied into Square. Choose either of these two workflows; do
not redeem the same reward through both.
### Option 1: the customer redeems from their pass
The customer opens their Apple Wallet or Google Wallet pass details and
chooses **Available rewards → Redeem**, or opens **My Account** and selects
an available reward. They need an internet connection. Wait until staff are
ready to honour the reward; simply showing an available reward is not a
redemption.
The customer selects the reward and the correct location if prompted, then
slides to redeem. Perkstar validates eligibility, records the redemption and
consumes the relevant reward or points. Wait for the live **Redeemed**
confirmation; an error or pending screen is not confirmation.
Staff check the business, reward and live countdown on the customer's
screen, then apply the agreed complimentary item or discount in Square using
their normal till procedure. The fresh confirmation lasts three minutes. A
screenshot, an available-reward screen or an expired confirmation must not
be accepted as a fresh redemption.
This is customer-led redemption: staff do not need to open Perkstar Scanner
for the supported reward. Staff still verify and fulfil it; Perkstar does
**not automatically apply a Square discount** or link the redemption to a
Square basket. The live screen is a staff check, not Square payment validation.
### Which Square-earned rewards can customers redeem themselves?
| Perkstar reward | From the pass |
| - | - |
| Stamp card | Available, unexpired stamp reward vouchers, including eligible bonus rewards |
| Points card using **Reward tiers** | A configured reward tier the customer's available points cover |
| Points status-tier benefit or a separately granted offer | When shown as available and its programme rules allow it |
| Points redeemed as a cash amount | Staff-assisted redemption; the pass does not let customers choose a monetary debit |
| Cashback balance | Staff-assisted redemption; the pass does not let customers spend the cashback balance |
Self-redemption uses the existing card and reward configuration; there is no
Square-side self-redemption switch. The programme and enrolment must be active,
and the reward must be available under its expiry, location and usage rules.
Other Perkstar card types can have their own pass-redemption options, but that
does not make them eligible for Square payment earning.
Sliding to redeem consumes the reward in Perkstar immediately; it is not a
reservation awaiting Square checkout. Closing the screen or letting the
three-minute confirmation expire does not restore it. If checkout is
cancelled, the confirmation expires before service, or a staff member is
unsure whether it was already honoured, check the customer's Perkstar activity
and resolve it with an authorised team member. Do not redeem again or apply a
second discount. A Square refund corrects the supported earning from that
payment; it does not automatically restore a separately redeemed Perkstar
reward.
### Option 2: staff redeem using Perkstar Scanner
The customer presents their Apple Wallet or Google Wallet pass. Staff scan
it with Perkstar Scanner and confirm the correct member.
Choose the available reward and complete the redemption. Wait for Perkstar
to confirm it so the member's balance and audit trail remain authoritative.
Add the corresponding complimentary item or discount in Square using the
business's normal till procedure, then complete checkout.
Do not create a parallel reward or loyalty balance in Square. Perkstar is the
source of truth, and Square is the till where staff apply the matching item or
discount after a confirmed Perkstar redemption.
## Customer matching and privacy
For optional scan setup, current customer consent is required before Perkstar
searches the connected Square directory, creates or links a profile, or
publishes a reference. For a consenting customer, it exact-searches by stable
reference, email and available phone without importing the directory. A unique
existing customer can be linked; only if none exists may Perkstar create a
profile from the member's name and contact details. Perkstar writes the stable
Wallet scan value only into an empty `reference_id`, preserves every foreign
value, and later releases only a value it can prove it owns.
The customer can change this choice by opening the customer-account link on the
back of their Wallet pass, then choosing **Preferences → Square customer
identification**.
For an ordinary attributed payment, Perkstar still reads only the attached
Square customer. Its email address or phone number is transient matching input
for an existing Perkstar member. A successful match creates an opaque identity
link scoped to that Square merchant and installation. Contact details from an
unmatched Square profile are discarded and are not used for marketing.
If exact email and phone evidence points to different Perkstar members, neither
field silently outranks the other. The payment awards nothing and remains queued
for a safe retry while Perkstar opens a merchant-visible **Customer match** case.
Correct the duplicate or member contact details; do not manually adjust a balance
while the case is open. The case summary and support link contain only the safe
operational wording and Perkstar case ID, not customer contact details or Square
identifiers.
For corrections and delayed events, continue to [Refunds and troubleshooting](/integrations/square/refunds-troubleshooting).
# Square
Source: https://developers.perkstar.co.uk/integrations/square/index
Connect Square to Perkstar for customer-attributed earning, location-aware programme routing and matched refund corrections.
Use completed Square payments to reward customers who have already joined a
Perkstar programme. Staff attach the existing Square Customer before payment
with Square's normal customer search. On a tested compatible device, the
business can also enable optional Wallet QR identification so staff use
**Review sale → Add customer → scan icon** instead. Perkstar applies the routed
programme's earning rule and updates the member's Wallet pass.
Customers can redeem eligible rewards themselves from their pass and show staff
the live confirmation, or staff can use Perkstar Scanner. Staff then apply the
matching item or discount in Square; it is not applied automatically. See the
[redemption options and supported rewards](/integrations/square/earning-redemption#redeem-a-reward).
Square is a **production beta** available to eligible Scale businesses through
Perkstar's direct installer. The integration is not currently listed in the
Square App Marketplace, but a Marketplace listing is not required to connect
or use it.
A business can start Square earning with valid programme routing and Square's
normal customer search. Optional Wallet QR device acceptance and the separate
Perkstar redemption workflow are not prerequisites for connecting or earning.
On a tested compatible device, identify a consenting member with one Wallet
QR scan. Exact matching, consented profile creation and reference ownership
all fail closed.
Route the Square location to an eligible Stamp, Points or Cashback programme
and credit a completed payment exactly once.
Full and partial refunds against the original Square payment reverse the
corresponding Perkstar credit safely.
## System boundaries
Perkstar is the loyalty system of record. Square supplies merchant, location,
completed-payment, refund and attached-customer signals. In the standard
workflow, staff find and attach the Square Customer before payment; email or
phone must exactly match an existing member of the routed Perkstar programme.
If the business enables optional Wallet QR identification, current customer
consent gates every Square search, link and reference publication. For a
consenting customer, Perkstar may exact-match an existing Square Customer,
create one from their name and contact details only if no match exists, and put
that member's stable Wallet scan value in an otherwise empty Square Customer
`reference_id`.
**Square Loyalty is not required.** Perkstar never creates or updates Square
payments, loyalty balances or rewards, and it does not request Square Loyalty
permissions. Customer write access is used only for the optional identification
flow described above.
| Event | What Perkstar does |
| - | - |
| Staff finds and attaches a Square Customer | Uses the attached profile as transient matching input |
| Staff scans a prepared Wallet QR on a tested device | Square finds and attaches the linked Square Customer |
| Completed payment with an attached matched customer | Applies the selected programme's earning rule once |
| Anonymous payment | Ignores it because no customer can be identified |
| Attached customer who has not joined Perkstar | Discards the unmatched contact without retaining or enrolling it |
| Full or partial refund | Reverses the supported share of the original Perkstar credit once |
| Reward redemption | Records redemption in Perkstar; staff complete the matching till adjustment in Square |
## What you need
* A Perkstar **Scale** plan or another plan that includes POS Connect.
* Owner access or a team role with **Edit operations** in Perkstar.
* Permission to approve apps for the intended Square production account.
* At least one active, earn-ready Stamp, Points or Cashback programme.
* Customers enrolled in Perkstar before the payment you want to reward.
* For one-scan identification: an individual default programme with a QR code
and required First name and Email fields.
Connect safely, choose the default programme and review every location.
Give staff the exact customer, payment and reward workflow.
Reconcile corrections, diagnose missing credit and disconnect safely.
## Data use
For payment earning, Perkstar reads the Square merchant and location profile,
completed payments and refunds, and only the customer attached to a payment.
Email or phone is used transiently to find an existing Perkstar member. If no
member matches, the contact is not retained, enrolled or used for marketing.
Optional Wallet-card identification does nothing in Square without current
customer consent. For a consenting customer, it performs complete exact
searches by the stable scan reference, email and, when available, phone. If the
searches resolve to one Square Customer, Perkstar links that profile. If none
resolves, Perkstar may create a Square Customer from first name, optional
surname, email and optional phone. Perkstar writes the stable Wallet scan value
only when `reference_id` is empty, never overwrites a value owned by the
merchant or another system, and releases only a value for which it has durable
ownership evidence.
After a successful match, Perkstar stores an opaque Square customer link scoped
to that merchant and connection. It also stores encrypted OAuth credentials,
card and location routing, and the operational and loyalty records required to
deduplicate earning and reconcile refunds. See [Set up Square](/integrations/square/setup)
for the permissions and test procedure.
Need help with a Square connection? Email
[support@perkstar.co.uk](mailto:support@perkstar.co.uk) with the Perkstar
business name, approximate payment or refund time, and Square location name.
Never send an access token, raw webhook payload, payment-card data or customer
contact details.
# Square refunds and troubleshooting
Source: https://developers.perkstar.co.uk/integrations/square/refunds-troubleshooting
Reconcile full and partial Square refunds, diagnose missing earning and disconnect the Square integration safely.
## Refunds
Process the refund in Square against the **original payment**. Completed full
and partial refunds reverse the corresponding Perkstar credit. Partial refunds
use the proportional share supported by the original award and rounding rules;
combined corrections never reverse more than the original credit.
Corrections are based on the original credited amount, not a fresh calculation
using today's programme rules or a returned item's category. Points corrections
round to two decimal places; stamps and cashback minor units round down until
the cumulative refunded amount justifies the next unit. For example, half of a
one-stamp payment can reverse zero stamps; a full refund reverses that stamp.
Square refunds are payment-level: there is no item-by-item or tip-only refund
allocation. Review those adjustments with support before promising an exact
loyalty outcome.
If the customer has already used the loyalty value, Perkstar does not force a
negative balance. It records a case requiring review. A refund also does not
undo a discount that staff already applied at the till. Check any earned or
redeemed rewards as part of that review.
Square may report a refund while its payment or refund is still changing state.
Perkstar waits for a terminal completed record, handles out-of-order delivery,
and uses recovery reconciliation for missed notifications. Repeated delivery of
the same refund is safe.
The five-minute recovery job discovers missed **refunds**. For payments,
recovery relies on Square's webhook retries and Perkstar's durable inbox; there
is no general automatic historical payment import. Contact support if a
completed, attributed payment is still absent—do not manually add loyalty
while a delayed payment may still be processed.
Do not make a manual loyalty correction while a Square refund is pending or
under review. That can duplicate the automatic reversal. Record the original
payment, refund time and Square location, then check the integration page.
## Troubleshooting
Confirm Square setup is complete, the explicit default programme is
eligible, and the selling location is not paused or invalid. The payment
must be completed and have a Square customer attached before payment. That
profile must match an existing member of the routed Perkstar programme by
email, phone, a previously established opaque link or the owned Wallet scan
reference.
Use **Review sale → Add customer → scan icon**, not the payment barcode
screen. Confirm Wallet-card scanning is on, the default programme is an
individual active QR programme, and First name and Email are required. If
the connection predates customer write access, reconnect Square. On Square
Terminal or Register running Square Point of Sale, open **Settings →
Checkout → Customer Management** and enable both **Scan customers using
device camera** and **Show Add customer button during checkout**. **Show Add
customer button after checkout** is optional; after-checkout attachment
alone is not sufficient for Perkstar earning. Keep Square for Retail or
Restaurants current. Test a Handheld or physical scanner against an
on-screen Wallet QR before relying on it. If the device cannot scan the
member there, use Square's normal customer search to attach the matching
Square Customer before payment. A conflicting exact match or non-empty
foreign reference is left unchanged and appears as an attention item in
Perkstar.
Square identification is optional and requires that customer's explicit
Square Customer Directory consent before any exact search, link, creation or
Wallet-reference publication. The member can grant or withdraw it from the
Perkstar join surface. To change it later, they open the customer-account
link on the back of their Wallet pass, then choose **Preferences → Square
customer identification**. Without consent, Perkstar leaves Square
unchanged.
OAuth alone does not start earning. Choose an eligible unrestricted default
programme, review every Square location, and repair any incompatible
override. A location-restricted programme also needs an allowed Perkstar
reporting location linked to that Square location.
Joining Square is not the same as joining Perkstar. Ask the customer to join
the routed Perkstar programme first, use the same email or phone on both
records, then attach the Square customer before a new payment. An earlier
anonymous or unmatched payment is not credited retrospectively, and the
unmatched contact is not retained.
That is expected. Square Loyalty is not required or written. The customer
can redeem an eligible reward from their pass and show staff the live
confirmation, or staff can redeem using Perkstar Scanner. Staff then apply
the corresponding item or discount in Square; it is not automatic. Follow
the [redemption
guide](/integrations/square/earning-redemption#redeem-a-reward) for
eligibility, confirmation checks and cancelled-checkout handling.
Confirm the refund was completed against the original Square payment. Allow
the terminal update and recovery reconciliation to finish before changing
the member's balance manually. If an operational issue remains on the Square
integration page, record the time and contact Perkstar support.
If the seller is still listed with **Reconnect**, automatic token renewal
failed or the current access expired. Reauthorise that same Square seller
through the direct Perkstar installer. Perkstar replaces its credential in
place and retains the saved default programme and location routes. If the
connection was revoked or explicitly disconnected and the seller row was
removed, start a fresh installation and configure the default programme and
routes again.
Square is available as a production beta through Perkstar's direct installer
and is not currently listed in the Square App Marketplace. A Marketplace
listing is not required. Confirm the organisation has Scale/POS Connect and
that you are an owner or have **Edit operations**. If it still will not
open, contact Perkstar support.
## Disconnect safely
An organisation owner or team member with **Edit operations** can disconnect
Square from **Settings → Integrations → Square**. New Square work stops
immediately. Perkstar revokes the Square grant and removes encrypted
credentials, merchant and location routing, opaque Square customer links,
Square-sourced operational data and retained webhook payloads.
Before local ownership evidence is purged, Perkstar attempts to clear only a
Square Customer `reference_id` whose live value and durable ownership record
both prove Perkstar set it. Foreign, merchant-edited and merely coincidental
values are never removed. Square Customer profiles, including consent-created
profiles, remain under the merchant's control.
Existing de-identified Perkstar-authored loyalty balances and ledger entries
remain so customers do not lose rewards already earned. A later reconnection is
a fresh installation and requires the default programme and every location
route to be configured again.
Disconnect only after all expected refunds have settled. Once the Square
payment link and credentials are removed, a later Square refund for a payment
from the disconnected installation cannot be reversed automatically in
Perkstar; contact support for a reviewed correction. If access is revoked in
Square before disconnecting in Perkstar, Perkstar may also be unable to clear a
Wallet QR reference it previously owned. The merchant can clear that stale
`reference_id` from the Square Customer record or ask support for guidance.
Email [support@perkstar.co.uk](mailto:support@perkstar.co.uk) with the
Perkstar business name, approximate payment or refund time, and Square
location name. Never send an access token, raw webhook body, payment-card data
or customer contact details.
# Set up Square
Source: https://developers.perkstar.co.uk/integrations/square/setup
Install the Square production beta, approve limited customer access, configure routing and enable optional Wallet-card identification.
Complete setup before taking a customer test payment. Authorising Square is the
first step; earning remains paused until the merchant has an explicit eligible
default programme and its location routing is valid.
Square is a **production beta** installed directly through Perkstar. Use
Perkstar's direct installer; it is not currently listed in the Square App
Marketplace, but a Marketplace listing is not required to connect or use the
integration.
Direct-install readiness uses the standard Square customer-search path:
connect, finish programme and location routing, then complete matched-payment
and refund checks. Optional Wallet QR device acceptance and a Perkstar reward
redemption are not prerequisites for Square earning.
## Before you connect
* Use the **Scale** plan or another plan that includes **POS Connect**.
* Sign in as the organisation owner or a team member with **Edit operations**.
* Be authorised to approve apps for the intended Square production account.
* Prepare at least one active, unarchived, earn-ready Perkstar programme.
* Ask a test customer to join that Perkstar programme before the test sale.
* To use one-scan identification, make the default programme individual, use a
QR barcode, and require First name and Email on its sign-up form.
### Eligible programmes
| Programme | Eligible earning rule |
| - | - |
| Stamp | Ordinary Stamp, spend-based or visit-based earning with a valid rate |
| Points | Spend-based or visit-based automatic earning with a positive rate |
| Cashback | A configured first tier with a positive cashback percentage |
Discount, Multipass, Membership, Coupon, Gift and Ticket cards cannot receive
Square payment earning. A programme restricted to selected Perkstar locations
cannot be the global default; route it only from a Square location linked to one
of its allowed Perkstar locations.
## Connect the merchant
You can also find Square from **Integrations → Marketplace** in Perkstar's
navigation. On a phone, open the menu first. Search for **Square**, open its
details and choose **Setup**. After connecting, use **Integrations → My
integrations** to return to management. This is Perkstar's integration catalogue,
not a claim that the app is listed in Square's App Marketplace.
[Connect Square](https://dashboard.perkstar.co.uk/install/square), then sign
in or create your Perkstar account. Select the eligible Scale organisation
you want to connect if asked.
Confirm the merchant you intend to connect and read how customer matching,
storage and disconnect work. Choose **Continue to Square** only if you are
authorised for that Square business.
Sign in to the correct Square production account and approve
`MERCHANT_PROFILE_READ`, `CUSTOMERS_READ`, `CUSTOMERS_WRITE` and
`PAYMENTS_READ`. Customer write access supports optional Wallet-card
identification only. Perkstar does not request payment write or Square
Loyalty permissions.
Back in Perkstar, check the Square business name, merchant identifier,
country and currency. If the wrong merchant was authorised, disconnect it
before configuring or taking a test payment.
## Choose the programme and locations
Open **Settings → Integrations → Square** and select the programme that
should receive payments by default. No organisation-primary or first-card
fallback is used.
Each location can inherit the default programme, use another eligible
programme, or pause loyalty. Do not leave an active selling location in an
invalid route.
Link the Square location to the corresponding Perkstar location for
reporting. This link is required before a location-restricted programme can
be selected as that Square location's override.
The Square page reports setup as incomplete while the default programme or
any location route is ineligible. Correct every warning before testing.
## Attach the customer before payment
The standard workflow does not require Wallet QR identification. Staff use
Square's normal customer search and attach the existing Square Customer before
payment. The customer must already belong to the routed Perkstar programme, and
the attached Square profile's email address or phone number must exactly match
that member. When both fields are supplied, every exact match must identify the
same member. If email and phone point to different members, Perkstar awards
nothing, keeps the payment queued for retry and opens a merchant-visible
**Customer match** case until the duplicate or contact data is corrected.
Anonymous or unmatched payments do not earn.
## Enable optional Wallet QR identification
This optional feature lets Square identify a consenting Perkstar member from
the QR code already displayed on their Apple Wallet or Google Wallet pass.
Existing Square connections that do not include `CUSTOMERS_WRITE` must
reconnect before the feature can be enabled; ordinary attached-customer earning
remains available while it is off.
Use an active, unarchived individual programme. Select **QR** as its barcode
format and make **First name** and **Email** required on the sign-up form.
In **Settings → Integrations → Square**, review the matching, creation and
reference-ownership acknowledgement, then choose **Enable scanning**.
Perkstar offers optional consent on the join surface. To change the choice
later, the customer opens the customer-account link on the back of their
Wallet pass, then chooses **Preferences → Square customer identification**.
Current consent is required before any Square directory search, link or
Wallet-reference publication. For a consenting customer, Perkstar
exact-matches an existing Square Customer or, only if none exists, may
create one from their first name, optional surname, email and optional
phone.
In Square, open **Review sale → Add customer → scan icon**, scan a test
member's Wallet QR and confirm the correct Square Customer is attached
before payment. Follow the device checklist below.
### Square device and app checklist
| Square setup | Required preparation |
| - | - |
| Square Point of Sale on Terminal or Register | Open **Settings → Checkout → Customer Management**. Enable **Scan customers using device camera** and **Show Add customer button during checkout**. **Show Add customer button after checkout** is optional; after-checkout attachment alone is not sufficient for Perkstar earning. Attach the customer before payment. |
| Square for Retail or Square for Restaurants | QR and barcode customer scanning is enabled automatically. Keep the app and device current, then test an on-screen Wallet QR on every device. |
| Square Handheld or a physical scanner | Compatibility depends on the installed Square app and hardware. Enable any **Scanning for screens** option and test the exact device. Do not promise Wallet QR customer attachment until that test passes. |
Square's current instructions are in its [customer QR and barcode scanning
guide](https://squareup.com/help/gb/en/article/7387-identify-customers-at-your-counter-with-qr-codes).
A physical scanner must be able to read a QR code displayed on a phone. If
Wallet QR scanning is unavailable, staff use Square's normal customer search to
attach the matching Square Customer by email or phone before payment.
### Safe matching and reference ownership
* Without current Square-directory consent, Perkstar does not search, link or
publish a Wallet reference.
* For a consenting customer, Perkstar exhausts exact searches by the stable
Wallet reference, email and, when available, phone. Conflicting or incomplete
results are left unchanged for review.
* A unique existing Square Customer can be reused. Only if no exact match exists
may Perkstar create a profile from the disclosed fields.
* Perkstar writes only the enrolment's stable `posBarcodeValue` into an empty
Square Customer `reference_id`.
* A non-empty `reference_id` is never overwritten, even if it resembles a
Perkstar value without recorded ownership.
* Turning the feature off, customer withdrawal, erasure or Square disconnect
releases only a live reference value that Perkstar can prove it owns. The
merchant's Square Customer remains.
## Test before serving customers
Use a synthetic member and record the expected result from the selected
programme's exact earning rules.
1. Confirm the test customer has already joined the routed Perkstar programme.
2. Use Square's normal customer search to attach a Square Customer whose email
or phone exactly matches the synthetic Perkstar member.
3. Complete a small payment and confirm the standard attached-customer path
credits the expected stamps, points or cashback once and refreshes the Wallet
pass.
4. Refund part of that original payment and confirm the supported proportional
correction appears once.
5. Refund the remainder and confirm the total correction never exceeds the
original award.
6. If the business enables optional Wallet QR identification, opt the synthetic
member in, test either a unique existing Square Customer exact match or
consented creation, then scan the Wallet QR on every supported device and
confirm the intended Square Customer is attached before payment. Also test a
Square Customer with a non-empty foreign `reference_id`; Perkstar must not
overwrite it.
7. If optional Wallet QR identification was enabled, turn it off and confirm
only proven Perkstar-owned references are cleared.
8. Before offering redemption, agree the actual priced reward item or discount
and train staff on the chosen workflow: customer self-redemption from the
pass for supported rewards, or Perkstar Scanner. Test one genuinely
available reward, verify Perkstar's saved redemption and remaining balance,
and check the matching Square item/discount and currency. Do not manually
set a balance to manufacture a successful test or incur charges without
permission. A pass redemption does not automatically discount Square.
Continue with the [staff earning and redemption guide](/integrations/square/earning-redemption).
# Stripe Connect
Source: https://developers.perkstar.co.uk/integrations/stripe/index
Connect the business payment account and check payout readiness.
Connect the business's Stripe account for supported customer payments and payout
readiness. This is separate from the Stripe subscription the business pays to
Perkstar, and separate from [Resend sending](/integrations/resend).
## Connect
1. Open **Integrations → Stripe Connect → Connect** in the intended business.
2. Follow Stripe's hosted onboarding and confirm the legal business and payment
account details. Complete any requirements Stripe requests.
3. Return to the Perkstar workspace and inspect account and payout readiness.
4. If onboarding remains incomplete, use the continuation action and complete the
outstanding provider requirements. Do not create a duplicate payment account.
## Confirm it is ready
Authorisation alone does not mean that charging or payouts are enabled. Review the
provider's requirements and the intended paid-card or commerce setup. Use the
supported test workflow before accepting real customer payments; do not charge a
customer merely to check the integration.
## Ownership and recovery
The business owns its Stripe account and is responsible for accurate onboarding
information. Stripe controls its verification and payout requirements. Use the
workspace management action to reopen the provider account when permitted. If a
requirement cannot be resolved, contact support with the account and visible error;
never share banking credentials or secret keys in documentation or chat.
# SumUp POS Custom Loyalty
Source: https://developers.perkstar.co.uk/integrations/sumup-pos/index
Connect a SumUp POS store, activate its gateway and verify loyalty at checkout.
This integration uses **SumUp POS Custom Loyalty**. It is not a generic connection
to every SumUp card reader or payment product. Access requires the POS Connect
entitlement and release availability for the business.
## Connect the store
1. Open **Integrations → SumUp POS (Custom Loyalty) → Connect**.
2. Enter the store subdomain, optional display name and intended Perkstar loyalty
programme, then choose **Create gateway URL**.
3. In SumUp POS Backoffice, open **Apps → Loyalty → Custom Loyalty Settings**.
Paste the exact merchant gateway URL, name the connection Perkstar, enable it
and save.
4. Copy the **Verification Token** displayed by SumUp POS back into the Perkstar
workspace, then choose **Activate SumUp POS**. The gateway stays locked until
activation. Treat the token as a secret.
## Verify checkout
Use a controlled customer and scan their Wallet QR code. Check that the intended
programme and available rewards appear, then verify one completed sale against its
Perkstar transaction. Where product rewards are used, configure eligible product
SKUs and maximum product value before redemption. Do not assume a displayed reward
was settled until the completed-sale record confirms it.
## Recover safely
Retain the original sale reference when investigating retries. A repeated callback
must not grant the same reward twice. Check the store subdomain, programme mapping
and verification token before replacing a connection. Changing the programme can
affect future checkout eligibility and should be deliberate.
Disconnect through **Manage**, and remove or disable the corresponding Custom
Loyalty configuration in SumUp POS when retiring it. See the
[POS safety walkthrough](/guides/pos) for identity and duplicate handling.
# Sunmi
Source: https://developers.perkstar.co.uk/integrations/sunmi/index
Availability and next steps for Sunmi.
**No self-service installation.** Reviewed 13 September 2026. The status shown
in the intended business's dashboard is authoritative for that account.
Connect Sunmi Cloud locations for sales polling when the production connector is released. This reference covers an existing or restricted connection. It is not an invitation to start a new connection.
## What to do now
Open **Perkstar → Integrations** and inspect Sunmi. If it says **Coming soon**
or **Unavailable**, do not use an old setup URL or grant provider credentials to
work around it. Documentation and a provider's developer portal do not themselves
grant access to a Perkstar connector.
If you already have an approved connection, use **My integrations → Manage** where
available. Keep the original provider account and transaction references when
asking support about a failure. Do not disconnect a working installation merely
to test whether you can reconnect it.
## Discuss compatibility with support
Provide the business account number, provider product/version, country, relevant
store or location, and the loyalty workflow you need. Do not share passwords,
API keys or customer lists. Ask support to confirm both access and an appropriate
controlled test before relying on this connection for customer transactions.
For a bespoke connection, start with the [POS guide](/guides/pos) and
[API availability](/support/api-availability). A custom integration is a separate
implementation, not a way to enable an unreleased native connector.
# TikTok Pixel
Source: https://developers.perkstar.co.uk/integrations/tiktok-pixel/index
Configure TikTok Pixel measurement for supported customer journeys.
Send supported customer journey events to your business's TikTok Pixel account. This
is measurement, not a loyalty balance source or proof that a message was delivered.
## Configure the connection
1. Select the intended business in **Perkstar → Integrations → TikTok Pixel → Connect**.
2. Enter the **Pixel ID** and **Events API token** from the property or data source you
control in TikTok Events Manager.
3. Save in the integration workspace. These are business-level settings inherited
by its cards; do not paste a different business's credentials into a card.
4. A saved-secret hint means the secret is already stored. Leaving it untouched
preserves it; entering a replacement deliberately updates it.
## Check an event
Use a controlled test customer and a supported enrolment or loyalty journey with
the required recorded marketing consent. Inspect the matching event in TikTok Events Manager.
The implementation requires both the identifier and secret, plus the applicable
consent, before firing these events. A saved identifier alone is not a completed
verification.
## Troubleshooting and ownership
Check the correct business, identifier, saved secret and test customer's consent.
Provider reporting can differ from Perkstar transaction totals; attribution events
are not the accounting record. Do not remove consent requirements to make a test
appear. Keep secrets private and rotate them through the provider when necessary.
Use the available workspace controls to remove the configuration when retiring it,
then confirm with a controlled test that no new event is generated.
See [security and privacy](/fundamentals/security-privacy).
# Toast
Source: https://developers.perkstar.co.uk/integrations/toast/index
Availability and next steps for Toast.
**No self-service installation.** Reviewed 13 September 2026. The status shown
in the intended business's dashboard is authoritative for that account.
Connect Toast sales and customer activity when the production integration is released. This reference covers an existing or restricted connection. It is not an invitation to start a new connection.
## What to do now
Open **Perkstar → Integrations** and inspect Toast. If it says **Coming soon**
or **Unavailable**, do not use an old setup URL or grant provider credentials to
work around it. Documentation and a provider's developer portal do not themselves
grant access to a Perkstar connector.
If you already have an approved connection, use **My integrations → Manage** where
available. Keep the original provider account and transaction references when
asking support about a failure. Do not disconnect a working installation merely
to test whether you can reconnect it.
## Discuss compatibility with support
Provide the business account number, provider product/version, country, relevant
store or location, and the loyalty workflow you need. Do not share passwords,
API keys or customer lists. Ask support to confirm both access and an appropriate
controlled test before relying on this connection for customer transactions.
For a bespoke connection, start with the [POS guide](/guides/pos) and
[API availability](/support/api-availability). A custom integration is a separate
implementation, not a way to enable an unreleased native connector.
# Zapier data and security
Source: https://developers.perkstar.co.uk/integrations/zapier/data-security
Understand OAuth access, customer-data flow, consent, retention, deletion, and operational safeguards for Perkstar Zaps.
Connecting Zapier creates a new data flow chosen by the Perkstar business. The
business decides which Zap runs, which fields are mapped, which destination
apps receive them, and how long those destinations retain them.
This page explains product behaviour and implementation responsibilities. It
is not legal advice and does not replace the Perkstar [Privacy
Notice](https://dashboard.perkstar.co.uk/privacy), [Data Processing
Agreement](https://dashboard.perkstar.co.uk/dpa), [Terms of
Service](https://dashboard.perkstar.co.uk/terms), Zapier's terms, or the
business's own privacy review.
## Connection security
Users approve Perkstar's hosted OAuth flow. The official connection never
asks them to paste a Perkstar API key into a Zap field.
Every credential resolves to one Perkstar organisation, and API resources
are checked against that tenant boundary.
The consent screen describes the access used by the configured triggers,
actions, searches, and card selector. Perkstar still enforces every scope.
The connection can be revoked. Revocation stops future API access but does
not erase Zap history or copies already sent to another app.
The prepared OAuth grant uses Authorization Code flow with required S256
PKCE, one-hour access tokens, and single-use rotating refresh tokens. Perkstar
revokes the grant if an already-rotated refresh token is replayed. Each instant
trigger also receives a per-subscription signing secret; the official app verifies the
exact callback bytes and a five-minute HMAC timestamp before returning a Zap
record.
## Requested access
| OAuth scope | Used for |
| - | - |
| `CUSTOMERS_READ` | Find customers and resolve customer state needed by supported steps. |
| `CUSTOMERS_WRITE` | Create or update a customer. |
| `ENROLLMENTS_READ` | Find an enrolment, balance, status, or available Wallet links. |
| `CARDS_READ` | Load active cards into selectors and validate card-aware steps. |
| `EVENTS_READ` | Read the bounded recent event feed used to provide real trigger samples. |
| `WEBHOOKS_WRITE` | Create, configure, and delete app-owned event subscriptions as Zaps are enabled or disabled. |
| `MARKETPLACE` | Enrol a customer, record loyalty activity, and reverse an eligible transaction through the marketplace-safe endpoints. |
| `PUSHES_WRITE` | Send a Wallet push through the explicit action. |
The Zapier OAuth application cannot use these permissions to inspect or mutate
webhook endpoints created by a different OAuth application or user. Perkstar
also enforces tenant, plan, account-state, consent, card-type, and rate-limit
checks after the scope check.
## Data the app can process
| Feature | Potential Perkstar data | Why it is used |
| - | - | - |
| Instant triggers | Event ID/type/time, organisation ID, and the event-specific customer, card, enrolment, loyalty, purchase, membership, engagement, or booking fields | Start the selected Zap and provide its mapping fields. |
| Find Customer | Customer ID/number, contact and profile fields, consent flags, external reference, and lifecycle timestamps | Match the intended customer and return current state. |
| Find Enrolment or Pass | Customer/card IDs, status, balance/activity values, and available Wallet install URLs | Find the current programme relationship or pass link. |
| Customer actions | The identity, profile, consent, and external-reference fields mapped by the user | Create or update the intended customer. |
| Loyalty actions | Customer identifiers, card, amount/delta, stable transaction reference, note, and selected metadata | Enrol, record one compatible activity, or reverse the original transaction. |
| Wallet push | Enrolment ID, message, resolved merge fields, and delivery result | Send a business-authored message to eligible Wallet passes. |
The exact fields for each event are in the [webhook event catalogue](/reference/webhook-events).
Perkstar does not add customer email, name, or phone to every trigger merely to
make mapping convenient. Use a search only when the workflow needs current
profile data and is authorised to copy it.
## Responsibility model
```mermaid theme={null}
flowchart LR
Customer["Cardholder"] --> Business["Business using Perkstar\nNormally the controller"]
Business --> Perkstar["Perkstar\nNormally a processor"]
Business --> Zapier["Zapier and enabled Zap apps\nChosen by the business"]
Perkstar --> Zapier
Zapier --> Destination["Destination app"]
```
The business is responsible for determining its role and lawful purpose for
each destination, configuring access, giving required notices, and honouring
access, correction, deletion, objection, and consent rights across all copies.
Perkstar cannot govern a later Zap step after the data leaves Perkstar.
## Consent and messaging
* A loyalty enrolment does not automatically grant email, SMS, advertising, or
push-marketing consent.
* Treat Perkstar consent fields as purpose-specific state, not blanket
permission for every Zap destination.
* Keep the source, wording, time, and lawful basis needed to support any consent
assertion written from another app.
* **Send Wallet Push** enforces push-marketing consent. A `403` is a safety
outcome, not an error to route around.
* Never place payment-card data, passwords, health data, or other sensitive
free text in a loyalty note, push message, Zap field, or support request.
## Minimise and retain deliberately
1. Map only fields the next step needs.
2. Use opaque Perkstar IDs instead of copying a full profile where possible.
3. Limit who can edit the Zap and view Zap history.
4. Configure destination retention and logs; do not assume turning off the Zap
deletes historical tasks.
5. Avoid broad chat-channel messages containing contact details or feedback
text.
6. Redact customer payloads, OAuth tokens, unique hook target URLs, and Wallet
URLs from screenshots and support messages.
## Disconnect, deletion, and rights requests
Turning off a Zap stops future runs and deletes its corresponding app-managed
Perkstar instant-trigger subscription. Re-enabling the trigger creates a fresh
subscription and secret. Revoking the connected account stops future authorised
API calls and pauses its remaining owned subscriptions.
None of those actions automatically delete:
* completed Zap runs in Zap history;
* records created in a CRM, spreadsheet, chat tool, or other destination;
* source records that another app still controls; or
* Perkstar records the business is otherwise entitled or required to retain.
For a rights request, locate data by Perkstar ID and any stable external
reference, then apply the required export, correction, suppression, or deletion
in Perkstar, Zapier, and each destination. Test this process before a live Zap
copies customer data.
## Operational review
* [ ] The Zap owner, every connected app, and every person who can edit the Zap
are documented.
* [ ] The Zap uses the correct tenant and minimum necessary fields.
* [ ] Consent and suppression behavior is tested.
* [ ] Zap editors and Zap history viewers are restricted.
* [ ] Stable references make customer and transaction writes retry-safe.
* [ ] Revocation, trigger removal, and destination deletion are tested.
* [ ] Rights requests and incidents have named owners.
Report suspected credential exposure, unauthorised access, or a personal-data
incident to [privacy@perkstar.co.uk](mailto:privacy@perkstar.co.uk). For an
operational failure, follow [Zapier troubleshooting](/integrations/zapier/troubleshooting).
# Zapier
Source: https://developers.perkstar.co.uk/integrations/zapier/index
Connect Perkstar to other business tools with instant loyalty triggers and safe, scoped actions.
Connect Perkstar loyalty activity to the tools a business already uses. The
public Beta catalogue contains 29 instant triggers, including Wallet installs,
online card scans, per-enrolment expiry, lifecycle-group changes, referrals,
transactions, redemptions, memberships, and bookings. Ten focused actions can
find, create, or update customers, enrol them in a card, add stamps or visits,
award points, record purchases, redeem a balance, run a flexible loyalty write,
reverse a transaction, or send a consented Wallet push.
The official Perkstar app is available in **public Beta**. Open the [Perkstar
page in Zapier's App Directory](https://zapier.com/apps/perkstar/integrations)
to start a Zap or connect an account. No invitation or Perkstar API key is
required.
Authorise one Perkstar business through OAuth. No API key is copied into a
Zap or shared with another person.
Choose from 29 named triggers backed by Perkstar's durable webhook events.
Use 10 scoped actions, stable references, idempotent writes, and explicit
consent checks in production workflows.
## Availability
| Item | Current position |
| - | - |
| Zapier listing | [Public Beta in Zapier's App Directory](https://zapier.com/apps/perkstar/integrations); no invitation needed |
| Perkstar plan | Growth, Scale, Enterprise, or Franchise |
| Connection | Perkstar OAuth; one Perkstar business per connected account |
| Permissions | A Perkstar owner or authorised team member who can connect integrations |
| Triggers | 29 named instant webhook triggers; no customer-list or transaction-list polling |
| Actions and searches | 10 visible actions, two searches, and two Search-or-Create relationships |
Public Beta access does not remove Perkstar's account and plan requirements.
The person approving OAuth must already be able to access the intended Perkstar
business. Zapier's public listing does not create a Perkstar business or add a
person to an existing Perkstar team.
## What stays authoritative
Perkstar remains the system of record for customers, enrolments, Wallet passes,
loyalty balances, rewards, and outbound events. Zapier coordinates the workflow
and keeps its own Zap configuration and Zap history.
| Direction | What happens |
| - | - |
| Perkstar → Zapier | A selected Perkstar event starts a Zap with the event's documented fields. |
| Zapier → Perkstar | A Zap calls a supported public v1 operation using the connected business's OAuth grant. |
| Zapier → another app | The Zap sends only the fields the business maps into that step. |
| Another app → Perkstar | The Zap validates and writes only the fields accepted by the selected Perkstar action. |
Perkstar does not inspect or control later steps in a Zap. The business is
responsible for the destination app, field mapping, lawful purpose, retention,
and deletion of any copied customer data. Read [Data and security](/integrations/zapier/data-security)
before using personal data or marketing actions.
## Start here
Open the public listing, connect the correct Perkstar business, and test the
OAuth grant.
See all 29 triggers, 10 actions, two searches, required inputs, and
important boundaries.
Learn how subscriptions, retries, duplicate protection, testing, and replay
work.
Diagnose connection, sample-data, trigger, action, rate-limit, and consent
failures without exposing a secret.
For a problem in a Zap workflow, start with [Zapier
Support](https://zapier.com/app/get-help). Zapier receives the run context,
handles first-line troubleshooting, and sends Perkstar an actionable report
when the Perkstar step needs our help. Contact
[support@perkstar.co.uk](mailto:support@perkstar.co.uk) directly for a
Perkstar account, plan, business-selection, or OAuth-consent problem. Never
send either team an OAuth token, webhook target URL, or unredacted customer
payload.
# Zapier recipes
Source: https://developers.perkstar.co.uk/integrations/zapier/recipes
Build reliable Perkstar Zaps for customer onboarding, loyalty activity, operations, and consented messaging.
These workflow patterns use the [public Perkstar app on
Zapier](https://zapier.com/apps/perkstar/integrations). They are guided build
recipes rather than one-click templates: choose the named Perkstar steps, test
with controlled records, and keep the business's consent and retention rules in
every destination app.
## Add a new member to a CRM or sheet
**Trigger:** New Customer Enrolment
**Then:** Find Customer → create or update the record in the destination
Use the trigger's `enrollmentId`, `customerId` when present, `cardId`, `source`,
and `occurredAt` as durable context. Run **Find Customer** only when the
destination genuinely needs current profile fields; choose **Customer ID** and
map the trigger's `customerId` when it is available.
Joining a loyalty card is not blanket consent for email, SMS, advertising, or
another app's marketing list. Map a purpose-specific consent field only when
the business has auditable evidence for that destination and channel.
## Enrol an external lead and return available Wallet links
**Trigger:** A qualified lead or checkout in another app
**Action:** Enrol Customer in a Card
**Then:** Send the returned Apple or Google Wallet URL through an appropriate
transactional channel
1. Use a stable external customer reference from the source app.
2. Select the intended Perkstar card explicitly.
3. Map only the identity fields needed to find or create the customer.
4. Store the returned `customer.id` and `enrollment.id` in the source system.
5. If Wallet links are initially unavailable, use **Find Enrolment or Pass** later
instead of constructing a Wallet URL yourself.
## Record a purchase exactly once
**Trigger:** A paid or completed order in the commerce/POS app
**Action:** Add Stamp or Visit, Award Points, or Record Purchase
Map the source order or payment ID into the action's Source ID field. Perkstar
automatically adds the Zapier action/activity namespace. Add your own source or
store prefix when several stores can emit the same numeric value, for example:
```text theme={null}
shopify:store-12:order:94721
```
Choose the focused action that matches the selected card. Use **Record
Purchase** for cashback or discount cards and map the integer minor-unit total;
use **Add Stamp or Visit** or **Award Points** when the source already knows the
exact balance change. Every action requires a Perkstar card and stable source
activity/order ID. Use **Record Loyalty Activity** only when one Zap genuinely
needs to select the activity type dynamically.
Do not generate a new external transaction ID when Zapier retries a failed
task. A stable source ID is what prevents a delayed or repeated order event
from crediting loyalty twice.
## Reverse a refunded purchase
**Trigger:** A completed refund in the source app
**Action:** Reverse Loyalty Transaction
Prefer the original Perkstar transaction ID saved by the earn Zap. If only the
source order/payment ID is available, choose **Original Source Transaction ID**,
select the exact Perkstar action that recorded it, and map the unchanged source
ID. You can instead map the original action's exact returned External
Transaction ID. Perkstar writes a compensating ledger row and returns an
existing reversal if the same original was already reversed.
Partial-refund business rules differ by integration. Agree the policy before
turning the Zap on; the action does not infer a proportional reversal from an
arbitrary source payload.
## Notify a team about a loyalty event
**Trigger:** Reward Redeemed, Loyalty Tier Changed, Feedback Submitted, or
another named event
**Then:** Send a message to the team's approved operations channel
Include the Perkstar event `id`, business timestamp, and opaque customer or
enrolment ID needed to investigate. Avoid copying full contact details or
free-text feedback into a broad channel. Link authorised staff back to the
Perkstar dashboard when possible.
## Send a consented Wallet reminder
**Trigger:** A deliberate business rule in another app
**Action:** Find Enrolment or Pass → Send Wallet Push
* Confirm the workflow has a clear customer purpose.
* Target one current enrolment.
* Map the source trigger's stable record ID into **Source Event ID**; keep it
unchanged when Zapier retries.
* Keep the message at or below 180 characters after merge-field expansion.
* Expect `403` when push-marketing consent is absent.
* Respect the shared three-minute per-card cooldown and `Retry-After` on `429`.
* Do not loop a bulk list directly into rapid per-customer sends without an
upstream rate and frequency cap.
## Production checklist
* [ ] The Zap owner, connected Perkstar business, and destination owner are
recorded.
* [ ] Every write uses the narrowest action and an explicit card where needed.
* [ ] Purchase flows use a stable permanent external transaction ID.
* [ ] Duplicate, delayed, and out-of-order trigger tests are safe.
* [ ] Consent and suppression behavior is tested with both allowed and blocked
records.
* [ ] `429`, non-retryable `4xx`, and destination-app failures are visible to an
operator.
* [ ] A disconnect, rights request, and downstream deletion procedure exists.
For launch failures, use [Troubleshooting](/integrations/zapier/troubleshooting).
# Connect Perkstar to Zapier
Source: https://developers.perkstar.co.uk/integrations/zapier/setup
Open the public Perkstar app, authorise one business with OAuth, and test a safe first Zap.
The official Perkstar app is available in Zapier's public App Directory. The
person connecting it signs in to Perkstar, chooses the intended business,
reviews the requested access, and approves the connection. Zapier never asks
the user to paste a Perkstar API key.
Start from the [official Perkstar listing on
Zapier](https://zapier.com/apps/perkstar/integrations). It is marked **Beta**
and is available without an invitation. A page or similarly named app that
asks for a raw Perkstar API key is not the official connection flow.
## Before you connect
* The Perkstar business is on Growth, Scale, Enterprise, or Franchise.
* You can sign in to both the intended Perkstar and Zapier accounts.
* Your Perkstar role can connect integrations for the business.
* At least one active loyalty card exists for card-based actions and filters.
* You know which Zap owner, destination apps, and customer fields the workflow
will use.
One Zapier connection represents one Perkstar business. If you operate more
than one business, create a separate connected account for each one. You can
reuse the same connected account in multiple Zaps for that business; there is
not a one-Zap-per-connection limit.
## Connect the account
Open the [Perkstar App Directory
page](https://zapier.com/apps/perkstar/integrations), sign in to the Zapier
account that will own the workflow, and choose a Perkstar trigger or action.
You can instead open Zapier's **App connections**, select **Add
connection**, and search for **Perkstar**.
Add a Perkstar trigger, action, or search and select **Sign in** when Zapier
asks for a connected account. Zapier opens Perkstar's hosted authorisation
page over HTTPS.
Confirm the business name and account shown by Perkstar. If it is wrong,
stop and switch account or organisation before approving. The resulting
OAuth grant is tenant-scoped and cannot read or write another business.
Read the plain-language permissions on the Perkstar consent screen. The app
requests the access needed by its available triggers, actions, searches, and
card selector. Perkstar returns a revocable OAuth grant to Zapier; no raw
API key is displayed.
Give the connected account a name that identifies the business, for example
`Perkstar — North Street Coffee`. Run Zapier's connection test and confirm
the returned business is the one you intended.
The public Zapier listing gives access to the integration; it does not create a
Perkstar login. If you are joining an existing business, accept that business's
Perkstar team invitation first and then return to Zapier. If you do not yet use
Perkstar, create the business account and eligible plan before authorising the
connection.
## Build the first Zap
Start with a reversible or read-only workflow before sending customer messages
or changing loyalty balances.
Pick one named Perkstar trigger, or use **Find Customer** / **Find Enrolment
or Pass** to prove the connection without changing data. The full list is in
the [catalogue](/integrations/zapier/triggers-actions).
Card-aware steps load the active cards from the connected Perkstar business.
Focused loyalty actions show only compatible programmes: Stamp/Multipass for
Add Stamp or Visit, Points for Award Points, and Cashback/Discount for
Record Purchase. Redeem Loyalty Balance supports Stamp, Points, Cashback,
and Multipass balances; coupons, memberships, discounts, gift cards, and
tickets use different flows. Select an explicit card when the business has
several eligible programmes. Never paste a card name where a card ID is
expected.
Use an internal test customer whose data you are authorised to process. For
an instant trigger, ask Zapier to test the trigger and perform the exact
Perkstar event it is waiting for. For an action, verify the previewed inputs
before running the test.
Confirm Zapier received the expected fields and, for a write, confirm the
Perkstar customer, enrolment, transaction, or push result. A successful Zap
step is not proof that a later destination step used the correct field.
Turn the Zap on for one card or low-risk workflow first. Monitor Zapier Task
History and the relevant Perkstar records before widening the audience.
When a workflow should continue after a search miss, use Zapier's explicit
**Find or Create Customer** or **Find or Enrol Customer in a Card** option. For
trigger enrichment, choose **Customer ID** in **Find Customer** and map the
trigger's `customerId`; this avoids a second identity guess from email or phone.
## Connection lifecycle
| Change | Effect |
| - | - |
| Turn a Zap off | Zapier stops the workflow and deletes its app-managed Perkstar instant-trigger subscription. Historical tasks remain under Zapier's retention settings. |
| Remove an instant trigger | Zapier deletes the corresponding Perkstar webhook subscription. Re-enabling creates a fresh callback subscription and signing secret. |
| Reconnect the account | Future steps use the renewed OAuth grant; stable subscription/action retries remain scoped to the same business grant. Test every enabled Zap afterwards. |
| Revoke Perkstar access | API calls fail and owned instant subscriptions are paused until the account is reconnected or the Zap is recreated. |
| Remove a destination app | Perkstar cannot remove data already copied into that app. Delete or retain it under the business's own policy. |
To revoke the connection from Perkstar, open **Settings → Authorised apps** for
the connected business and revoke Zapier. Then remove or reconnect the account
in Zapier before re-enabling any affected Zaps.
Read [Troubleshooting](/integrations/zapier/troubleshooting) before reconnecting
an account used by several live Zaps, and read [Data and security](/integrations/zapier/data-security)
before mapping personal data.
## Get support
For a problem in a Zap workflow, start with [Zapier
Support](https://zapier.com/app/get-help). That route includes the Zap and run
context Zapier needs for first-line troubleshooting; Zapier will escalate an
actionable Perkstar integration report to us when necessary. Contact [Perkstar
Support](mailto:support@perkstar.co.uk) directly when the OAuth page shows the
wrong Perkstar business or the issue concerns a Perkstar account, plan, team
invitation, or consent screen.
Before contacting support, keep the failed run in Zap history and note
the step name, approximate UTC time, Zap run/task ID, and any Perkstar
`X-Request-Id`. Redact customer data and never send passwords, OAuth tokens,
refresh tokens, or webhook target URLs.
# Triggers, actions, and searches
Source: https://developers.perkstar.co.uk/integrations/zapier/triggers-actions
The exact operations in the public Perkstar app for Zapier, including event names and safety boundaries.
The public Beta catalogue contains 29 instant triggers, 10 visible actions, two
searches, and two explicit Search-or-Create relationships. Zapier subscribes to
one Perkstar webhook event when the Zap is enabled and deletes that app-managed
subscription when the trigger is disabled or removed.
Open [Perkstar in Zapier's App
Directory](https://zapier.com/apps/perkstar/integrations) to use this
catalogue without an invitation. The app is in public Beta, so event payloads
can gain new optional fields; map only the fields your Zap needs.
## Instant triggers
The integration defines one named Zapier trigger for each real business event below.
The diagnostic `webhook.test` event is deliberately excluded from the Zapier
catalogue.
### Customer lifecycle
| Zapier trigger | Perkstar event | Fires when |
| - | - | - |
| New Customer Enrolment | `customer.enrolled` | A customer first joins a loyalty card. |
| Customer Unenrolled | `customer.unenrolled` | Access to a card ends. |
| Customer Anonymised | `customer.anonymized` | Perkstar removes the customer's direct identifiers. |
| Customer Lifecycle Group Changed | `customer.group_changed` | A customer moves between Perkstar's six exclusive lifecycle groups. |
The lifecycle-group trigger does not represent an operator-created saved
segment. Perkstar stores a customer's first classification as a baseline and
does not emit it, preventing a newly connected Zap from receiving every
existing customer.
### Wallet, scanner, expiry, and referrals
| Zapier trigger | Perkstar event | Fires when |
| - | - | - |
| Wallet Pass Installed | `wallet.installed` | Perkstar first observes an Apple or Google Wallet install; Google observation is periodic rather than immediate. |
| Card Scanned | `card.scanned` | An online Perkstar Scanner lookup successfully resolves a customer card; offline cache-only lookups do not fire. |
| Customer Card Expired | `card.expired` | One enrolment reaches its effective expiry; a later expiry after extension can produce another event. |
| New Customer Referral | `referral.created` | One customer refers another customer to a Perkstar loyalty-card programme. |
`referral.created` is customer-to-customer loyalty activity. It is not a
merchant, agency, or partner-referral event.
The first group-change or Google-install trigger in a business establishes a
no-event baseline on the next completed periodic sweep. Tracking begins after that
warm-up; Apple installs remain callback-driven, and post-subscription expiries
retain their effective expiry time while waiting for projection.
The five trigger records flatten these event fields for later Zap steps:
| Trigger | Event-specific fields |
| - | - |
| Customer Lifecycle Group Changed | `customerId`, `previousGroup`, `currentGroup`, `occurredAt` |
| Wallet Pass Installed | `walletPassId`, `enrollmentId`, `customerId`, `cardId`, `platform`, `detectionSource`, `installedAt`, `occurredAt` |
| Card Scanned | `scanId`, `enrollmentId`, `customerId`, `cardId`, `credentialType`, nullable `walletPassId`, nullable `platform`, nullable `locationId`, `occurredAt` |
| Customer Card Expired | `enrollmentId`, `customerId`, `cardId`, `cardType`, `expiresAt`, `expirySource`, `occurredAt` |
| New Customer Referral | `referralId`, `cardId`, `referrerEnrollmentId`, `referrerCustomerId`, `referredEnrollmentId`, `referredCustomerId`, `status`, `bonusTiming`, nullable `creditedAt`, `occurredAt` |
### Loyalty activity
| Zapier trigger | Perkstar event | Fires when |
| - | - | - |
| New Loyalty Transaction | `transaction.created` | A supported loyalty-ledger row commits, including a compensating reversal. |
| Coupon Redeemed | `coupon.redeemed` | A coupon card is redeemed. |
| Reward Redeemed | `reward.redeemed` | A reward, offer, voucher, or milestone is redeemed. |
| Loyalty Tier Changed | `tier.changed` | A status, cashback, or discount tier changes. |
### Tickets, gifts, and multipasses
| Zapier trigger | Perkstar event | Fires when |
| - | - | - |
| Ticket Purchased | `ticket.purchased` | Paid ticket fulfilment completes. |
| Ticket Cancelled | `ticket.cancelled` | A ticket event is cancelled. |
| Ticket Refunded | `ticket.refunded` | A ticket payment is refunded or lost to chargeback. |
| Gift Card Purchased | `gift.purchased` | Paid gift fulfilment completes. |
| Gift Card Redeemed | `gift.redeemed` | Value is spent from a gift card. |
| Multipass Purchased | `multipass.purchased` | A multipass is purchased or topped up. |
### Memberships
| Zapier trigger | Perkstar event | Fires when |
| - | - | - |
| Membership Purchased | `membership.purchased` | A recurring or one-off membership first activates. |
| Membership Renewed | `membership.renewed` | A recurring membership advances to a new billing period. |
| Membership Cancelled | `membership.cancelled` | A recurring membership becomes cancelled or incomplete-expired. |
### Engagement
| Zapier trigger | Perkstar event | Fires when |
| - | - | - |
| Feedback Submitted | `feedback.submitted` | A customer submits card feedback. |
| Automation Fired | `automation.fired` | A Perkstar automated-message firing is recorded. |
| Broadcast Sent | `broadcast.sent` | A Wallet broadcast reaches terminal delivery processing. |
### Bookings
| Zapier trigger | Perkstar event | Fires when |
| - | - | - |
| Booking Created | `booking.created` | A booking is created. |
| Booking Confirmed | `booking.confirmed` | A booking moves to confirmed. |
| Booking Attended | `booking.attended` | Attendance is recorded. |
| Booking Marked as No-Show | `booking.no_show` | A booking is resolved as a no-show. |
| Booking Cancelled | `booking.cancelled` | A booking is cancelled. |
The official app accepts the event at its unique Zapier REST Hook URL and then
exposes a mapping-friendly record:
| Zapier field | Meaning |
| - | - |
| `id` | Unique event/delivery ID; automatic delivery retries retain it. |
| `event_type` | Dotted Perkstar event name. |
| `event_created_at` | Source event time as an ISO 8601 timestamp. |
| `organization_id` | Connected Perkstar business ID. |
| Event-specific fields | The raw `data` fields flattened onto the record, such as `customerId`, `cardId`, or `occurredAt`. |
For booking events, the raw `data.id` is exposed as `resource_id` so it cannot
replace the trigger's primary `id`. See the [webhook event catalogue](/reference/webhook-events)
for required, optional, and nullable event fields. The app keeps documented
optional mapping fields present with `null` when the live event omits them, but
does not enrich every trigger with a customer profile. Add **Find Customer**
only when the event carries a customer ID and the Zap needs current contact
fields.
### Trigger options
* **Card (Optional)** is available on every named trigger except **Customer
Anonymised**, **Customer Lifecycle Group Changed**, and **Automation Fired**.
Leaving it blank accepts the event from every card.
* **Include Test Events** appears on **New Loyalty Transaction** and **Reward
Redeemed**. It is off by default so test API activity cannot start live
downstream steps; enable it only in a dedicated test Zap.
## Actions
Non-idempotent write actions use deterministic idempotency keys; customer
updates are naturally repeatable PATCHes. Loyalty activity and Wallet pushes
require the source app's stable transaction or event ID; use a real record ID
rather than a timestamp or random value. Perkstar automatically namespaces each
loyalty source ID by Zapier action and activity type. Retrying the same action
and source ID remains safe, while reusing an order ID for a different loyalty
operation cannot replay the wrong transaction. References that would exceed the
API's 180-character limit use a deterministic SHA-256 form.
Every POST-based Zapier action checks the current OAuth credential before it
looks for an earlier response. Refreshing the access token for the same
Perkstar connection preserves retry protection, while a revoked connection is
denied instead of replaying an earlier success.
The four focused loyalty actions provide guided fields for common merchant
jobs. **Record Loyalty Activity** remains available for workflows that need to
choose the activity type dynamically.
Each source transaction ID is permanently bound to its first canonical
customer, card, operation, and amount. An exact Zapier retry returns the
original result; reusing that ID with different inputs stops with a conflict
instead of silently returning or changing the first transaction.
All four focused loyalty actions and **Record Loyalty Activity** include
**Create Customer If Missing**, which defaults **off**. Leave it off when the
workflow should reward only existing members. Turn it on deliberately when a
lookup miss should create the customer and enrol them in the selected card
before applying the loyalty write. A missing or cross-business Customer ID is
never treated as permission to create a replacement customer.
| Zapier action | What it does | Important boundary |
| - | - | - |
| Create Customer | Creates a customer, or returns the existing customer when a matching `external_ref` is supplied. | Without `external_ref`, a duplicate email can return a conflict instead of overwriting a profile. |
| Update Customer | Updates the mapped fields on one existing Perkstar customer. | Blank or omitted mappings must be reviewed carefully; this action does not anonymise or delete a customer. |
| Enrol Customer in a Card | Finds a customer by Customer ID, email, phone, external reference, or pass barcode; can create a missing customer; and enrols them in the required active card. Returns available Apple/Google Wallet links. | An existing active pair is returned. An inactive or revoked pair halts for review rather than being silently reactivated; Wallet links can initially be `null`. |
| Add Stamp or Visit | Adds a positive whole number of stamps or visits to an active Stamp or Multipass card. | Its selector shows only Stamp and Multipass cards, and a mapped incompatible Card ID is rejected. A stable Source Activity ID supplies permanent duplicate protection. |
| Award Points | Adds a positive points amount, including up to two decimal places where the card permits it. | Its selector shows only active Points cards. The amount cannot exceed 100,000; a stable Source Points Award ID supplies permanent duplicate protection. |
| Record Purchase | Records an integer minor-unit purchase amount on an active Cashback or Discount card. | Its selector shows only Cashback and Discount cards. The purchase amount must be positive; a stable Source Order or Payment ID supplies permanent duplicate protection. |
| Redeem Loyalty Balance | Deducts a positive whole-number balance or prepaid visit from an active Stamp, Points, Cashback, or Multipass card without allowing the balance below zero. | Its selector excludes Coupon, Membership, Discount, Gift, and Ticket cards, which have separate or no balance-redemption flow. A mapped incompatible Card ID is rejected. |
| Record Loyalty Activity | Finds or creates the customer and enrolment when allowed, then records one compatible Stamp, Redeem, Check-in, Discount, or Points activity through `/marketplace/accrue`. | The Card and Source Transaction ID are required. Card-type mismatches fail, and the source ID supplies permanent duplicate protection. |
| Reverse Loyalty Transaction | Creates one compensating transaction for an eligible transaction previously recorded through Perkstar's marketplace API, found by Perkstar transaction ID, original source ID plus action, or exact external transaction ID. | A transaction can be reversed once. The action does not edit or delete the original ledger row. |
| Send Wallet Push | Sends a plain-text message of up to 180 characters to one enrolment's eligible Wallet passes. | Enrolment ID and Source Event ID are required. Push-marketing consent and a three-minute per-card cooldown are enforced; success cannot guarantee device display. |
### Action inputs
| Action | Required | Optional |
| - | - | - |
| Create Customer | At least one of Email Address, Phone Number, or External Reference | First/last name, date of birth, marketing/ad-tracking consent, Unique Request ID |
| Update Customer | Customer ID and at least one profile or consent field to update | Profile and consent fields that are not changing may be omitted |
| Enrol Customer in a Card | Find Customer By, Customer Lookup Value, Card | Create Customer If Missing (defaults on), first/last name for a new customer, Enrolment Source |
| Add Stamp or Visit | Find Customer By, Customer Lookup Value, Card, Stamps or Visits to Add, Source Activity ID | Note, Create Customer If Missing (defaults off), first/last name |
| Award Points | Find Customer By, Customer Lookup Value, Card, Points to Award, Source Points Award ID | Note, Create Customer If Missing (defaults off), first/last name |
| Record Purchase | Find Customer By, Customer Lookup Value, Card, Purchase Amount (Minor Units), Source Order or Payment ID | Note, Create Customer If Missing (defaults off), first/last name |
| Redeem Loyalty Balance | Find Customer By, Customer Lookup Value, Card, Balance to Redeem, Source Redemption ID | Note, Create Customer If Missing (defaults off), first/last name |
| Record Loyalty Activity | Find Customer By, Customer Lookup Value, Card, Activity Type, Source Transaction ID | Purchase Amount (Minor Units), Balance Change, note, Create Customer If Missing (defaults off), first/last name |
| Reverse Loyalty Transaction | Find Transaction By and Transaction Reference | Original Perkstar Action when using the original source ID; Reason |
| Send Wallet Push | Enrolment or Pass, Message, Source Event ID | None |
The loyalty action accepts the wire-level activity types supported by the
public endpoint: `STAMP`, `REDEEM`, `CHECK_IN`, `DISCOUNT`, and `POINTS`.
`DISCOUNT` requires a positive amount in integer minor units. `POINTS` requires
either a balance change (up to two decimal places) or a positive purchase
amount. The selected card's type determines which values are valid.
**Send Wallet Push** supports `{firstName}`, `{lastName}`, `{balance}`,
`{cardName}`, `{installLink}`, `{shareLink}`, and `{orgName}` merge fields. Map
the originating trigger's stable `id` into **Source Event ID** so a retry of the
same source event is collapsed within Perkstar's 24-hour idempotency window.
## Searches
| Zapier search | Matching behavior | Result |
| - | - | - |
| Find Customer | Looks up by exact Customer ID, email, phone, external reference, or pass barcode/serial. | Matching current customer records, or a not-found result the Zap can branch on. |
| Find Enrolment or Pass | Resolves Customer ID, email, phone, external reference, or pass barcode without creating records, then matches Card ID; status defaults to Active. | The same root result shape as Enrol Customer: nested customer and enrolment data plus available Wallet pass URLs. |
### Search-or-Create relationships
Zapier exposes both relationships explicitly, so a workflow can branch on a
search miss without constructing a custom API step:
| Zapier option | Search | Create action | Result on no match |
| - | - | - | - |
| Find or Create Customer | Find Customer | Create Customer | Creates the customer from the mapped identity/profile fields. |
| Find or Enrol Customer in a Card | Find Enrolment or Pass | Enrol Customer in a Card | Enrols the selected customer in the selected active card. |
The enrolment pair still requires a customer and card. Repeatedly selecting the
same customer/card pair returns the existing active enrolment rather than
creating a duplicate. Perkstar never undoes an inactive or revoked status
implicitly: if the Active search misses but the create step finds that status,
the action halts with instructions to review the enrolment.
The app uses hidden dynamic-field helpers that paginate through up to ten pages
of 200 cards (2,000 total) before filtering. General selectors show every active
card; Add Stamp or Visit shows only Stamp and Multipass cards, Award Points only
Points cards, Record Purchase only Cashback and Discount cards, and Redeem
Loyalty Balance only Stamp, Points, Cashback, and Multipass cards. These helpers
are not advertised as standalone actions. A mapped Card ID is still checked
when the focused action runs, so mapping an incompatible card does not bypass
the selector.
Searches return current API state, while a trigger contains the event snapshot
produced at the time of the business change. If a Zap must preserve the exact
event context, store the trigger values before running later searches.
## Behavior the app does not expose
* No action edits card configuration, rewards, tiers, coupons, or orders.
* No action bypasses Perkstar consent, plan, card-type, tenant, or rate-limit
checks.
* `webhook.test` is not a customer-facing Zapier trigger.
* A trigger does not promise customer email, name, or phone unless that field is
part of the documented event payload.
* Searches do not scan another Perkstar business connected to the same Zapier
account.
# Zapier troubleshooting
Source: https://developers.perkstar.co.uk/integrations/zapier/troubleshooting
Diagnose public-app access, OAuth, instant triggers, actions, searches, rate limits, and consent failures.
Start with Zap history and the connected Perkstar business. Record the
step name, event or request time, status, and any Perkstar `X-Request-Id` before
retrying. Never copy an OAuth token, unique hook target URL, or full customer
payload into a support message.
## Connection and access
Open the [official public Beta
listing](https://zapier.com/apps/perkstar/integrations), confirm you are
signed in to the intended Zapier account, and search for **Perkstar** rather
than a similarly named app. You can also use **App connections → Add
connection**. No invitation is required. If a managed Zapier workspace
restricts apps, ask its administrator to allow Perkstar.
The public listing does not create or join a Perkstar business. If you are
an existing team member, accept the Perkstar team invitation sent to your
exact email address and sign in with that account before reconnecting. Do
not create a second business just to authorise Zapier. If you are a new
customer, finish Perkstar account and plan setup first.
Zapier is available to Growth, Scale, Enterprise, and Franchise businesses.
Confirm the current Perkstar plan and that you are connecting the intended
business. Free and Starter businesses must upgrade before connecting.
Cancel instead of approving. Sign out or switch to the correct Perkstar
organisation, then start the connection again. One connected account is
tenant-scoped to one business.
One connected account is scoped to one Perkstar business, but it can be
reused across many Zaps. Add a separate Perkstar connection for each other
business and give each connection a clear name. A Zapier account can hold
multiple Perkstar connections.
Reauthorise the Perkstar connected account in Zapier, then test every
enabled Zap that uses it. If access was revoked in Perkstar, a new approval
is required; retrying the old task does not restore the grant.
## Instant triggers
Confirm the Zap uses the correct Perkstar business and named event. Start
the Zapier test/listen step first, then perform that exact event. If a card
filter is present, confirm the event belongs to the selected active card.
The diagnostic `webhook.test` event does not satisfy a business-event
trigger.
Check that the Zap is published and enabled, the connected account is still
authorised, and the expected Perkstar business event actually completed.
Inspect Zap history. Perkstar keeps app-managed delivery attempts out of the
custom-webhook dashboard so their callback URL and signing secret cannot be
changed behind Zapier's back; quote the event time and ID to Perkstar
support if Zap history is not enough.
Automatic retries keep one logical delivery ID and should deduplicate.
Confirm the runs have the same trigger `id`. Protect destination writes with
the Perkstar ID or another stable source reference.
This is allowed. Compare the event-specific `occurredAt` timestamp and the
destination's current state. The exposed `event_created_at` field expresses
that same source-event time in ISO 8601; the internal signing timestamp is
the delivery-attempt time.
Documented optional mapping fields can be `null` when they do not apply, and
trigger bodies are not automatically enriched with a customer profile.
Review the [event catalogue](/reference/webhook-events), guard optional
mappings, and add **Find Customer** or **Find Enrolment or Pass** only when
current state is appropriate.
Creating a pass or opening its save link is not installation evidence. Apple
normally reports installation through its device callback. Google is
observed periodically; recently issued passes are eligible on the 15-minute
projector, while object age, provider cadence, and projector backlog can
extend the delay. Check the Zap and pass again after a later completed sweep
rather than treating 15 minutes as an SLA. The trigger fires only for the
first observed install of that pass. A business's first Google-install
trigger uses its first check as a no-event baseline; tracking begins after
that warm-up, so enable and test the Zap before distributing install links.
**Card Scanned** covers successful online Perkstar Scanner lookups only. A
lookup served solely from the scanner's offline cache never reaches the
webhook boundary and does not fire this trigger. Dashboard searches and POS
customer lookups are also excluded.
The trigger reports movement between Perkstar's six exclusive lifecycle
groups, not entry into or exit from an operator-created saved segment. A
customer's first classification is stored as a baseline without an event,
preventing a new Zap from replaying the entire customer base. For the first
interested trigger in a business, allow one completed periodic sweep to
establish that baseline before expecting later transitions.
The event belongs to one enrolment and one effective expiry instant. If the
enrolment is extended or reissued and later reaches a different expiry,
another event is expected. Use `enrollmentId` plus `expiresAt` as the
business identity when the destination needs its own duplicate protection.
This trigger is customer-to-customer loyalty activity. It includes both the
referrer's and referred customer's IDs, but it does not represent an agency,
merchant, partner, or affiliate invitation.
## Searches and actions
| Symptom | Likely cause | What to do |
| - | - | - |
| Find Customer returns no match | Wrong lookup type/value, cross-business Customer ID, email casing/format issue, or exact phone format differs | Prefer the trigger's Customer ID or a stable external reference/pass barcode; use the same phone format the source stores. |
| Find Enrolment or Pass returns no Wallet URL | Pass issuance is still pending or that Wallet platform is not configured | Retry the search later; never construct an install URL. |
| Find or Enrol reports a revoked/inactive pass | The customer/card pair already exists and Perkstar will not silently undo its status | Review and explicitly reactivate the enrolment in Perkstar before retrying; do not create a duplicate customer. |
| A card is absent from a focused action | The card type is not valid for that action or the card is not active | Choose the matching action/card type; mapping an incompatible Card ID is rejected too. |
| `400 ambiguous_default_card` | The business has several active cards and no card was selected | Select the intended card explicitly in the Zap step. |
| `401` or connection error | OAuth grant is invalid, expired beyond recovery, or revoked | Reconnect the Perkstar account, then retest affected Zaps. |
| `403` permission error | The OAuth grant lacks the required access or the operation is not allowed for the business | Reauthorise the official connection and confirm plan/role eligibility; do not substitute a raw API key. |
| `403 push_marketing_consent_required` | The customer has not consented to marketing Wallet pushes | Stop the message. Obtain and record valid consent through an approved process before another marketing send. |
| `404` | Customer, enrolment, card, or original transaction does not belong to the connected business or no longer exists | Check the connection and mapped opaque IDs; do not reuse an ID from another business. |
| `409` creating a customer | A conflicting customer exists and the Zap did not use a stable `external_ref` upsert | Find the existing customer or provide the source system's stable external reference. |
| `409 external_transaction_id_conflict` | A loyalty Source ID was reused with a different customer, card, operation, or amount | Keep the original inputs for a retry, or use the genuinely different source record's own stable ID. |
| `409 webhook_subscription_limit_reached` | This OAuth connection owns 200 instant-trigger subscriptions, including paused rows from an interrupted cleanup | Turn off/remove unused instant triggers, confirm unsubscribe succeeds, then enable the new trigger again. |
| `422` recording loyalty | Activity does not match the selected card type or the source reference belongs to the other environment | Correct the card/activity mapping; never hide the error by generating a new transaction reference. |
| `429` | Credential rate limit or three-minute Wallet-push card cooldown | Let Zapier wait for `Retry-After`; reduce loops and burst frequency. |
| `5xx` or network timeout | Temporary Perkstar or network failure | Retry the same logical task with the same stable identifiers; check [API status](/support/status). |
## Safe replay
Before retrying or manually replaying a failed task:
1. Decide whether the earlier action may already have succeeded.
2. Keep the same source ID field value. Perkstar recreates the same
action-specific external transaction ID, including its deterministic hash
form when needed.
3. Fix a non-retryable validation, permission, or consent error first.
4. Retry from Zapier once and inspect the returned Perkstar record.
5. Replay once, then inspect the result before trying again.
To reverse a Zapier loyalty write, prefer its returned **Perkstar Transaction
ID**. If only the original source ID is available, select **Original Source
Transaction ID** and the exact Perkstar action that recorded it. If mapping the
returned **External Transaction ID**, map it exactly without removing the
`zapier:` namespace.
## Ask for help
For a problem in a Zap workflow, use [Zapier
Support](https://zapier.com/app/get-help) first. That route preserves the Zap
and run context for Zapier's first-line troubleshooting; Zapier will escalate
an actionable Perkstar integration report to us when needed. Contact [Perkstar
Support](mailto:support@perkstar.co.uk) directly for a Perkstar account, plan,
team invitation, business-selection, or OAuth-consent problem.
For a support request, keep the failed run in Zap history and
include:
* the Perkstar business name;
* the Zapier trigger, action, or search name;
* the approximate UTC time and Zap run/task ID;
* the Perkstar `X-Request-Id`, event ID, or delivery ID when available; and
* the status/code with secrets and personal fields removed.
Do not delete the failed history before support has finished tracing it. Never
send a password, OAuth token, refresh token, webhook target URL, or full
customer payload.
For suspected exposure or a personal-data incident, contact
[privacy@perkstar.co.uk](mailto:privacy@perkstar.co.uk) immediately.
# Instant triggers and webhooks
Source: https://developers.perkstar.co.uk/integrations/zapier/webhooks
Understand how Zapier subscribes to Perkstar events, handles retries, deduplicates deliveries, and manages hooks.
Perkstar's named Zapier triggers use REST-hook subscriptions. When a Zap with a
Perkstar trigger is enabled, Zapier registers its HTTPS callback for that one
dotted Perkstar event. Perkstar sends the event as it happens; Zapier does not
poll the customer or transaction lists to discover changes.
The official app is [available in public
Beta](https://zapier.com/apps/perkstar/integrations). Let it create and manage
these subscriptions. Do not also paste a **Webhooks by Zapier — Catch Hook**
URL into Perkstar for the same event unless you intentionally want two
independent deliveries.
## Subscription lifecycle
Zapier first creates a paused Perkstar webhook for the selected trigger and
retains its signing secret. It then explicitly activates the subscription
with the unique, unguessable Zapier HTTPS target URL, event, card, and
live/test filters. If activation fails, Zapier asks Perkstar to delete the
unused endpoint instead of delivering to a Zap whose setup did not finish.
The target URL is not exposed as a Zap field.
Perkstar durably creates the delivery before scheduling the outbound POST.
Events that do not match that named trigger, selected card, or live/test
mode are rejected before a delivery row or outbound request is created.
Any `2xx` response is success. Zapier then deduplicates and starts the Zap
run using the event fields.
When Zapier unsubscribes the trigger, it deletes the app-managed Perkstar
endpoint by the ID returned during subscription. Re-enabling the trigger
creates a fresh endpoint and signing secret. Historical Zapier tasks remain
under Zapier's retention settings.
One Zapier OAuth connection can own up to 200 Perkstar webhook subscriptions,
including a paused row left by an interrupted cleanup or revoked connection.
Each enabled instant trigger normally uses one, and a successful Zapier
unsubscribe deletes it and releases capacity. If the connection reaches the
limit, turn off or remove unused instant triggers and confirm their unsubscribe
completed before enabling another one; Perkstar returns
`409 webhook_subscription_limit_reached` instead of silently replacing an
existing subscription.
Perkstar derives Zapier's subscription identity from the connected business and
named trigger plus the Zap ID when the runtime supplies it. Zapier marks that
field deprecated and optional, so the official integration falls back to the
documented REST Hook target URL instead of refusing activation. Perkstar binds
the resulting key to the live webhook row rather than a 24-hour response cache.
A lost create response, access-token rotation, delayed retry, failed unsubscribe,
or reconnect with the same identity can recover the row and secret. When the Zap
ID is available, a changed callback URL recovers it too. The activation PATCH
applies the current URL, card, and live/test filters. Deleting the row removes
the binding immediately, so an off/on cycle cannot be given a deleted
subscription ID or a stale cached capacity error.
The first **Customer Lifecycle Group Changed** or Google **Wallet Pass
Installed** trigger for a business needs one completed warm-up sweep. Perkstar
records existing state without replaying the customer base, then tracks
changes after that baseline. If the first workflow must catch every new Google
install, enable and test the Zap before promoting its install link. Apple
installation remains callback-driven.
## Event identity
Perkstar sends the official app this common envelope:
```json theme={null}
{
"id": "whd_01JEXAMPLE",
"type": "transaction.created",
"created": 1785312000,
"orgId": "org_123",
"data": {
"enrollmentId": "enr_123",
"type": "STAMP",
"delta": 1,
"occurredAt": "2026-08-02T10:00:00.000Z"
}
}
```
`id` and `X-Perkstar-Delivery-Id` identify one logical delivery and remain
stable across its **automatic retries**. `created` is the source event's
`data.occurredAt` time expressed as Unix seconds, so it also remains stable.
The `X-Perkstar-Timestamp` signing time and signature are regenerated for each
attempt. Zapier uses the stable ID to avoid starting the same logical task
twice.
The app exposes `id`, `event_type`, `event_created_at`, and `organization_id` to
later Zap steps. It flattens the event-specific `data` fields onto the same
record. `event_created_at` is the raw `created` value rendered as ISO 8601; it
is not the signing-attempt time.
Custom webhook endpoints support manual resend in Perkstar. Zapier-owned
subscriptions are app-managed and intentionally hidden from those edit, rotate,
delete, test, and resend controls.
## Delivery policy
| Attempt | Timing |
| - | - |
| 1 | Immediately |
| 2 | 1 minute after the first failure |
| 3 | 5 minutes after the second failure |
| 4 | 30 minutes after the third failure |
* Any HTTP `2xx` response succeeds.
* A non-`2xx`, network failure, or response taking longer than ten seconds
schedules the next attempt.
* An HTTP `410 Gone` response is treated as a permanently removed callback:
Perkstar exhausts that delivery immediately and pauses the subscription.
* After four failed attempts, the delivery is exhausted and retained for
support diagnostics.
* Delivery is at least once. A receiver and every downstream write must tolerate
duplicates.
* Different events can arrive out of order. Use `data.occurredAt` or its
equivalent outer `created` value for business ordering, not the signing
timestamp.
## Signature handling
Perkstar signs the exact raw body with HMAC-SHA256 and sends
`X-Perkstar-Signature: t=,v1=`. Zapier's REST Hooks runtime
stores Perkstar's one-time subscription secret and makes it available to the
live hook handler. Perkstar returns it only on creation or an authenticated
idempotent replay of that same app-owned subscription; normal reads never expose
it. The official app verifies the signature over the exact raw
bytes with a constant-time comparison and rejects timestamps more than five
minutes from receipt. Zapier also gives every active Zap a unique HTTPS target
URL; do not disclose or reuse it.
Developers building a separate receiver should follow [Receive webhooks](/guides/webhooks)
and apply the same raw-body verification before parsing JSON. Zapier does not
support a separate subscription identity-confirmation handshake; callback HMAC
verification is performed inside the official app instead.
## Testing an instant trigger
1. Select the named trigger and the intended Perkstar connected account.
2. If the trigger offers a card filter, choose the explicit active card.
3. Ask Zapier to test or listen for the trigger.
4. Perform the corresponding low-risk event in the connected Perkstar business.
5. Confirm `event_type`, `organization_id`, `event_created_at`, the flattened
event-specific fields, and the stable `id` before mapping later steps.
The test picker requests up to 20 of the most recent matching records from
Perkstar's 90-day recent-event feed. The feed defaults to live events. **New
Loyalty Transaction** and **Reward Redeemed** also offer **Include Test Events**;
when enabled, both live and test records may be returned. A Card filter, when
offered, applies to both recent samples and live delivery. Perkstar applies
these filters before sending to Zapier; the app checks them again before
starting a Zap run.
The diagnostic `webhook.test` event is for Perkstar's generic webhook tools and
is not exposed as a named Zapier trigger. If no recent match exists, perform the
corresponding low-risk event and test again. A sample is not evidence that every
optional field will be non-null on a later live event.
## Timing and scope of observed triggers
Some triggers are emitted when Perkstar observes a provider or calculated
state, rather than directly from a merchant API request:
* **Wallet Pass Installed** fires once when Perkstar first obtains installation
evidence for that pass. Apple supplies a device-registration callback.
Recently issued Google passes are eligible on the 15-minute projector; older
unseen objects use a lower check cadence, and provider responses or projector
backlog can extend observation time. Issuing a pass or opening its save link
does not fire the trigger.
* **Card Scanned** fires only after a successful online lookup in the Perkstar
Scanner. An offline cache-only lookup, dashboard search, or POS customer
lookup is outside this trigger's contract.
* **Customer Card Expired** represents one enrolment reaching one effective
expiry instant. If that enrolment is extended and later reaches a different
effective expiry, another event can fire. `event_created_at` reflects the
expiry instant, even if projection occurs shortly afterwards.
* **Customer Lifecycle Group Changed** represents movement among Perkstar's six
exclusive lifecycle groups. It does not track saved-segment membership, and
an existing customer's initial baseline classification is intentionally
suppressed.
* **New Customer Referral** is created when one loyalty customer refers another
customer. It does not report Perkstar merchant, agency, or partner referrals.
Some trigger bodies contain customer or purchaser data. Zap history and every
downstream step can retain mapped values. Use only the fields the workflow
needs and follow [Data and security](/integrations/zapier/data-security).
# Your first safe POS test
Source: https://developers.perkstar.co.uk/quickstart
Record one test stamp, prove retries do not duplicate it, and check a signed webhook receipt.
Use this small workflow when connecting a till: **one completed sale earns one
stamp on an existing stamp-card enrolment**. The downloadable example uses the
real API and is checked against isolated database fixtures in our release tests.
It refuses live keys. It does not create customers or send wallet notifications.
A test key can still read the business's real records. Use a dedicated test
customer/enrolment agreed with the business, not a customer chosen at random.
Test transactions can also trigger webhooks: use a test receiver, and make
sure any endpoint set to receive both live and test traffic handles
`data.testMode` correctly. The example does not create or alter webhooks.
## 1. Agree the business, owner and minimum access
The business needs API access through its POS Connect entitlement (Scale,
Enterprise or Franchise, including an eligible active trial). If key creation
is unavailable, ask the owner to check the plan and your permissions; do not
borrow another business's key.
The business owner creates the key in **Settings → API keys → Create API key**.
Select **Test** and only **Enrolments: read** (`ENROLLMENTS_READ`) and
**Transactions: write** (`TRANSACTIONS_WRITE`). No customer-write, enrolment-write,
webhook-write or broad read-only preset is needed.
Name it for the system and responsible maintainer, such as `Till setup — Alex`.
Set an expiry covering the agreed test period; revoke it when testing ends.
The business owns the key and can revoke it. The developer owns its secure
storage and the receiving server. Perkstar cannot show the full key again.
Keep the secret in a private file named `.perkstar-test.env`, excluded from
source control. Set restrictive file permissions (for example `chmod 600
.perkstar-test.env` on macOS/Linux). Do not put it in browser code, screenshots,
support messages or a shell command that will remain in history.
```dotenv theme={null}
PERKSTAR_API_KEY=pk_test_replace_me
PERKSTAR_API_URL=https://dashboard.perkstar.co.uk/api/v1
PERKSTAR_ORG_ID=replace_with_business_id
PERKSTAR_CARD_ID=replace_with_active_stamp_card_id
PERKSTAR_ENROLLMENT_ID=replace_with_existing_test_enrollment_id
PERKSTAR_RECEIPT_ID=test:my-till:store-1:receipt-0001
```
The business ID here is the API's `organization.id`, not the six-digit account
number in the dashboard URL. Read `GET /marketplace/ping` with the test key to
check the business and its active cards. Read `GET /enrollments?cardId=` to
find the agreed enrolment; follow `next_cursor` if necessary. Inspect these
responses privately. Never select the first business or enrolment automatically.
The script verifies the business, test mode, scopes, active stamp card and
matching active enrolment **before writing**.
## 2. Download, inspect and run the example
Use **Node.js 24 or later**. There are no packages to install.
[Download pos-test-quickstart.mjs](https://dashboard.perkstar.co.uk/developer-downloads/pos-test-quickstart.mjs)
Save the file, inspect it, then run:
```bash theme={null}
node --env-file=.perkstar-test.env pos-test-quickstart.mjs
```
The one-stamp request is:
```json theme={null}
{
"enrollment_id": "your_existing_test_enrollment_id",
"type": "STAMP",
"delta": 1,
"external_transaction_id": "test:my-till:store-1:receipt-0001"
}
```
It uses `POST /transactions` and the receipt ID as `Idempotency-Key`. This
example is for a completed sale earning **one stamp**, not a spend-to-stamp or
points calculation. Use the [POS guide](/guides/pos) for those workflows.
Amounts named `amount_pence` use the business currency's minor units; never
assume every currency uses two decimal places.
## 3. Check the result, repeat and exercise an error
| Check | Expected result |
| - | - |
| First request | `201` for a new row; `test_mode: true` and a transaction ID |
| Repeat identical request and key | Same transaction ID and original status, including `201`; `Idempotent-Replayed: true` |
| Same receipt with a different request-cache key | `200` and the same transaction ID: permanent receipt deduplication |
| `ADJUST` without a `delta` | `400`, `error.code: missing_field`, `error.param: delta`; no transaction |
| Read enrolment again | Balance, redemptions, spend and bonus balance unchanged |
The script runs all five checks and prints a compact `PASS` summary without
customer records or secrets. Run it again with the **same receipt ID**: it
should identify the same transaction. Each genuinely new sale needs its own
namespaced permanent reference. Do not generate a new reference on every retry.
A real customer being served during the check may change their balance through
another channel. That is why an isolated test enrolment is useful. A successful
script proves this small API workflow, not every card type or POS feature.
## 4. Receive a signed test event
[Download test-webhook-receiver.mjs](https://dashboard.perkstar.co.uk/developer-downloads/test-webhook-receiver.mjs)
The receiver accepts `transaction.created` only when `data.testMode` is `true`,
plus the dashboard's synthetic `webhook.test`. It validates the signature,
five-minute signing timestamp and business ID, then commits a minimal receipt
to a local SQLite file before returning `200`. It stores the delivery ID, event
type, transaction ID, time and a content hash; it does not store the full customer
payload, award another stamp or claim to fulfil an order.
Add the separate webhook signing secret to the private environment file:
```dotenv theme={null}
PERKSTAR_WEBHOOK_SECRET=replace_with_endpoint_signing_secret
PERKSTAR_RECEIPTS_DB=perkstar-test-receipts.sqlite
```
```bash theme={null}
node --env-file=.perkstar-test.env test-webhook-receiver.mjs
```
It listens on `127.0.0.1:8787/webhooks/perkstar`. Perkstar cannot deliver to your
localhost. Expose that exact path through an HTTPS ingress you control, then ask
the business owner to create a **separate test endpoint** in **Settings →
Webhooks**, subscribed to `transaction.created`, filtered to the selected card
and **Test** mode. The API test key cannot change webhook configuration. Keep
the existing production endpoints intact. Store the one-time signing secret in
the receiver's private configuration before testing delivery.
Use **Send test** to check connectivity. Then run the POS script with a new test
receipt to check a real test-transaction event. Check the endpoint's delivery
history and your receiver's receipt; webhook dispatch is asynchronous.
| Receiver check | Expected result |
| - | - |
| Valid signed test transaction | `200` and `receipt: stored` |
| Retry/manual resend after restarting the receiver | `200` and `receipt: duplicate`; one saved receipt |
| Missing, altered, old or future-dated signature | `400`; nothing saved |
| Different business | `403`; nothing saved |
| Live transaction | `422 live_event_refused`; nothing saved |
| Storage failure | `503`; no success acknowledgement, so Perkstar can retry |
The database file must survive restarts. Do not deploy this teaching receiver on
an ephemeral filesystem. Before production, use a durable inbox/queue shared by
all instances, process real business work asynchronously and make downstream
operations idempotent too. Do not simply remove the live-event rejection.
Node's built-in SQLite module may show an experimental warning on earlier Node
24 releases; see the [Node SQLite documentation](https://nodejs.org/download/release/latest-v24.x/docs/api/sqlite.html).
## If a check fails
* **401:** the key may be wrong or expired. Ask its owner to replace it;
do not print the secret while diagnosing it.
* **410:** the key has been revoked. Stop using it and ask its owner for a replacement.
* **403:** check the selected scopes and business access. Add only the missing
permission needed for the intended operation.
* **404:** verify the enrolment belongs to the chosen business/card.
* **409:** check reused request keys and receipt references. Changing a payload
is not a retry of the original operation.
* **429:** wait for `Retry-After` before rerunning with the same receipt ID.
* **Timeout/5xx:** the write may have succeeded. Keep the receipt ID unchanged,
inspect the outcome and use a bounded retry policy; never loop indefinitely.
* **Webhook 307/308:** enter the final HTTPS destination directly. Perkstar does
not follow redirects; confirm the exact route accepts POST.
* **Webhook timeout/5xx:** fix storage/availability and acknowledge promptly after
persistence. Resend an exhausted delivery only after correcting the receiver.
See [webhook recovery](/guides/webhooks) and [idempotency](/fundamentals/idempotency).
## Finish testing and move deliberately to production
Record the expected business, card, connection owner, expiry and successful
transaction/delivery IDs. Revoke temporary test keys and disable temporary test
endpoints. Keep or remove the local receipt database according to your test-data
retention policy. Do not run the all-test-transactions cleanup endpoint on a
shared business without agreement: it removes other developers' test rows too.
The owner then creates a **separate**, narrowly scoped live key for the finished
integration. Store it server-side, use distinct live receipt references, verify
one agreed real transaction, and monitor failures. This downloadable script
continues to refuse live keys. For future rotation, create a replacement with
the required overlap, check last-use evidence and revoke the old key when the
consumer has switched; an already expired key is not revived by rotation.
# Webhook event catalogue
Source: https://developers.perkstar.co.uk/reference/webhook-events
Every Perkstar outbound webhook event, with exact data fields and representative payloads.
This is the complete public outbound-event catalogue: 29 business events plus
the targeted `webhook.test` diagnostic. Event names are stable, dotted,
lowercase strings. New optional fields may be added without a version change;
existing fields are not repurposed.
Every example below shows the event-specific `data` object. Perkstar wraps it
in the common envelope documented in [Receive webhooks](/guides/webhooks).
## Field conventions
* IDs are opaque strings. Store and compare them exactly.
* `occurredAt`, `installedAt`, `expiresAt`, `creditedAt`, `scheduledStart`,
`scheduledEnd`, `attendedAt`, and `resolvedAt` are ISO 8601 UTC timestamps.
* `created` in the outer envelope is Unix seconds.
* Money fields ending in `Pence` are integer minor units.
* Nullable fields are sent as JSON `null`; optional fields may be absent.
* `testMode: true` identifies a transaction generated with test credentials.
## Customer lifecycle
| Event | Sent when | Required `data` fields | Optional `data` fields |
| - | - | - | - |
| `customer.enrolled` | A customer first joins a card | `enrollmentId`, `cardId`, `source`, `occurredAt` | `customerId` |
| `customer.unenrolled` | Access to a card ends | `enrollmentId`, `reason`, `occurredAt` | `cardId`, `customerId` |
| `customer.anonymized` | Personal data is anonymised | `customerId`, `customerNumber`, `occurredAt` | `source` |
| `customer.group_changed` | A customer moves between lifecycle groups | `customerId`, `previousGroup`, `currentGroup`, `occurredAt` | None |
```json theme={null}
{
"enrollmentId": "enr_123",
"customerId": "cus_123",
"cardId": "card_123",
"source": "marketplace",
"occurredAt": "2026-07-30T10:00:00.000Z"
}
```
```json theme={null}
{
"enrollmentId": "enr_123",
"customerId": "cus_123",
"cardId": "card_123",
"reason": "membership_cancelled",
"occurredAt": "2026-07-30T10:10:00.000Z"
}
```
```json theme={null}
{
"customerId": "cus_123",
"customerNumber": 1042,
"source": "api",
"occurredAt": "2026-07-30T10:15:00.000Z"
}
```
```json theme={null}
{
"customerId": "cus_123",
"previousGroup": "new",
"currentGroup": "regulars",
"occurredAt": "2026-07-30T10:20:00.000Z"
}
```
`previousGroup` and `currentGroup` use one of `vips`, `regulars`, `new`,
`slipping`, `atRisk`, or `lost`; `currentGroup` can be `null` if a customer no
longer classifies into a group. These are Perkstar's six exclusive lifecycle
groups, not operator-created saved segments. The first classification is stored
as a baseline without emitting `customer.group_changed`, so connecting a new
endpoint does not replay every existing customer. For a business's first
interested endpoint, that baseline is established on the next completed
projection. Tracking begins after the warm-up sweep, so a transition inside
that initial window becomes baseline state rather than an event.
## Wallet, scanner, expiry, and referrals
| Event | Sent when | Required `data` fields | Nullable `data` fields |
| - | - | - | - |
| `wallet.installed` | Perkstar first observes a pass installed in Apple or Google Wallet | `walletPassId`, `enrollmentId`, `customerId`, `cardId`, `platform`, `detectionSource`, `installedAt`, `occurredAt` | None |
| `card.scanned` | An online Perkstar Scanner lookup successfully resolves a customer card | `scanId`, `enrollmentId`, `customerId`, `cardId`, `credentialType`, `walletPassId`, `platform`, `locationId`, `occurredAt` | `walletPassId`, `platform`, `locationId` |
| `card.expired` | One customer enrolment reaches its effective card expiry | `enrollmentId`, `customerId`, `cardId`, `cardType`, `expiresAt`, `expirySource`, `occurredAt` | None |
| `referral.created` | One customer refers another customer to the same loyalty-card programme | `referralId`, `cardId`, `referrerEnrollmentId`, `referrerCustomerId`, `referredEnrollmentId`, `referredCustomerId`, `status`, `bonusTiming`, `creditedAt`, `occurredAt` | `creditedAt` |
```json theme={null}
{
"walletPassId": "pass_apple_123",
"enrollmentId": "enr_123",
"customerId": "cus_123",
"cardId": "card_123",
"platform": "apple",
"detectionSource": "apple_device_registration",
"installedAt": "2026-07-30T10:25:00.000Z",
"occurredAt": "2026-07-30T10:25:00.000Z"
}
```
```json theme={null}
{
"scanId": "550e8400-e29b-41d4-a716-446655440000",
"enrollmentId": "enr_123",
"customerId": "cus_123",
"cardId": "card_123",
"credentialType": "wallet_pass_serial",
"walletPassId": "pass_apple_123",
"platform": "apple",
"locationId": "loc_high_street",
"occurredAt": "2026-07-30T10:30:00.000Z"
}
```
```json theme={null}
{
"enrollmentId": "enr_123",
"customerId": "cus_123",
"cardId": "card_123",
"cardType": "POINTS",
"expiresAt": "2026-07-30T10:35:00.000Z",
"expirySource": "fixed_term",
"occurredAt": "2026-07-30T10:35:00.000Z"
}
```
```json theme={null}
{
"referralId": "referral_123",
"cardId": "card_123",
"referrerEnrollmentId": "enr_referrer_123",
"referrerCustomerId": "cus_referrer_123",
"referredEnrollmentId": "enr_referred_123",
"referredCustomerId": "cus_referred_123",
"status": "credited",
"bonusTiming": "on_signup",
"creditedAt": "2026-07-30T10:40:00.000Z",
"occurredAt": "2026-07-30T10:40:00.000Z"
}
```
### Observation boundaries
* `wallet.installed` is the first provider-owned installation observation per
pass and platform. Creating a pass or opening a save link is not an install.
Apple reports a device registration directly. Recently issued Google passes
are eligible on the 15-minute projector; older unseen objects back off to a
lower check cadence, and provider responses or projector backlog can extend
observation time. Do not treat 15 minutes as a delivery SLA. `platform` is
`apple` or `google`, and `detectionSource` is
`apple_device_registration` or `google_has_users`. When a business enables
its first interested endpoint, the next completed Google check stores existing state as
a no-event baseline; Google-install tracking begins after that warm-up sweep.
* `card.scanned` covers a successful **online** lookup in the Perkstar Scanner.
It does not fire for an offline IndexedDB cache lookup, a dashboard customer
search, or a POS integration lookup. `credentialType` is
`wallet_pass_serial`, `enrollment_barcode`, or `physical_keyring`.
`walletPassId` and `platform` are non-null only for a direct wallet-pass
serial; shared enrolment barcodes and physical keyrings are platform-neutral.
* `card.expired` is per enrolment and effective expiry instant, not one event
for the card template. `expirySource` is `enrollment_override`, `fixed_date`,
or `fixed_term`. Extending or reissuing the enrolment can produce another
event when the later effective expiry is reached.
* `referral.created` is a customer-to-customer loyalty referral. It is not a
merchant, agency, or partner-referral invitation. `status` is `pending` or
`credited`; `bonusTiming` is `on_signup` or `on_first_purchase`, and
`creditedAt` is `null` while a first-purchase referral remains pending.
## Loyalty activity
| Event | Sent when | Required `data` fields | Optional `data` fields |
| - | - | - | - |
| `transaction.created` | A loyalty-ledger row is committed | `enrollmentId`, `type`, `delta`, `occurredAt` | `transactionId`, `cardId`, `customerId`, `amountPence`, `balanceAfter`, `reversesTransactionId`, `reason`, `source`, `testMode`, `externalTransactionId`, `promotionId`, `promotionUseId`, `promotionUseVoided` |
| `coupon.redeemed` | A coupon card is redeemed | `enrollmentId`, `cardId`, `customerId`, `occurredAt` | None |
| `reward.redeemed` | A reward, offer, voucher, or milestone is redeemed | `enrollmentId`, `cardId`, `cost`, `occurredAt` | `transactionId`, `milestoneId`, `stampRewardId`, `rewardTierId`, `offerId`, `offerTitle`, `discountAmountPence`, `discountKind`, `basketAmountPence`, `source`, `testMode`, `promotionId`, `promotionName`, `promotionRewardKind`, `promotionRewardMultiplier`, `promotionRewardPercent`, `promotionRewardAmountPence`, `promotionRewardText`, `promotionCurrency`, `promotionTerms` |
| `tier.changed` | A status, cashback, or discount tier changes | `enrollmentId`, `cardId`, `newTierName`, `kind`, `occurredAt` | `source` |
`transaction.created.type` is normally `STAMP`, `REDEEM`, or `ADJUST`.
`tier.changed.kind` is `status`, `cashback`, or `discount`.
```json theme={null}
{
"transactionId": "txn_123",
"enrollmentId": "enr_123",
"customerId": "cus_123",
"cardId": "card_123",
"type": "STAMP",
"delta": 1,
"amountPence": 1250,
"balanceAfter": 6,
"externalTransactionId": "odoo:order:94721",
"promotionId": null,
"promotionUseId": null,
"promotionUseVoided": null,
"source": "api",
"testMode": false,
"occurredAt": "2026-07-30T11:00:00.000Z"
}
```
```json theme={null}
{
"enrollmentId": "enr_123",
"cardId": "card_coupon_123",
"customerId": "cus_123",
"occurredAt": "2026-07-30T11:05:00.000Z"
}
```
```json theme={null}
{
"transactionId": "txn_124",
"enrollmentId": "enr_123",
"cardId": "card_123",
"cost": 10,
"rewardTierId": "tier_123",
"promotionId": "promo_123",
"promotionName": "Double points weekend",
"promotionRewardKind": "MULTIPLIER",
"promotionRewardMultiplier": 2,
"promotionRewardPercent": null,
"promotionRewardAmountPence": null,
"promotionRewardText": "Double points",
"promotionCurrency": "GBP",
"promotionTerms": "Valid once per customer.",
"discountAmountPence": 500,
"discountKind": "FIXED",
"basketAmountPence": 2500,
"source": "api",
"testMode": false,
"occurredAt": "2026-07-30T11:10:00.000Z"
}
```
```json theme={null}
{
"enrollmentId": "enr_123",
"cardId": "card_123",
"newTierName": "Gold",
"kind": "cashback",
"source": "api",
"occurredAt": "2026-07-30T11:15:00.000Z"
}
```
## Tickets, gifts, and multipasses
| Event | Sent when | Required `data` fields | Optional `data` fields |
| - | - | - | - |
| `ticket.purchased` | A paid ticket fulfilment completes | `enrollmentId`, `cardId`, `pricePence`, `sessionId`, `firingId`, `occurredAt` | None |
| `ticket.cancelled` | A ticket event is cancelled | `cardId`, `cardName`, `cancellationId`, `attendeeCount`, `reason`, `willRefund`, `occurredAt` | None |
| `ticket.refunded` | A ticket payment is refunded or lost to chargeback | `enrollmentId`, `cardId`, `paymentIntentId`, `occurredAt` | `refundAmountPence`, `reason` |
| `gift.purchased` | A paid gift fulfilment completes | `giftPurchaseId`, `enrollmentId`, `cardId`, `amountPence`, `purchaserEmail`, `recipientEmail`, `occurredAt` | None |
| `gift.redeemed` | Value is spent from a gift card | `enrollmentId`, `customerId`, `cardId`, `amountPence`, `remainingPence`, `occurredAt` | None |
| `multipass.purchased` | A multipass is purchased or topped up | `enrollmentId`, `cardId`, `customerId`, `visitCount`, `bundleName`, `topUp`, `sessionId`, `firingId`, `occurredAt` | None |
```json theme={null}
{
"enrollmentId": "enr_ticket_123",
"cardId": "card_ticket_123",
"pricePence": 2500,
"sessionId": "checkout_session_123",
"firingId": "fulfilment_123",
"occurredAt": "2026-07-30T12:00:00.000Z"
}
```
```json theme={null}
{
"cardId": "card_ticket_123",
"cardName": "Summer tasting",
"cancellationId": "cancel_123",
"attendeeCount": 18,
"reason": "Venue unavailable",
"willRefund": true,
"occurredAt": "2026-07-30T12:05:00.000Z"
}
```
```json theme={null}
{
"enrollmentId": "enr_ticket_123",
"cardId": "card_ticket_123",
"refundAmountPence": 2500,
"paymentIntentId": "payment_123",
"occurredAt": "2026-07-30T12:10:00.000Z"
}
```
```json theme={null}
{
"giftPurchaseId": "gift_123",
"enrollmentId": "enr_gift_123",
"cardId": "card_gift_123",
"amountPence": 5000,
"purchaserEmail": "buyer@example.com",
"recipientEmail": "recipient@example.com",
"occurredAt": "2026-07-30T12:15:00.000Z"
}
```
```json theme={null}
{
"enrollmentId": "enr_gift_123",
"customerId": "cus_123",
"cardId": "card_gift_123",
"amountPence": 1250,
"remainingPence": 3750,
"occurredAt": "2026-07-30T12:20:00.000Z"
}
```
```json theme={null}
{
"enrollmentId": "enr_multi_123",
"cardId": "card_multi_123",
"customerId": "cus_123",
"visitCount": 10,
"bundleName": "Ten visits",
"topUp": false,
"sessionId": "checkout_session_456",
"firingId": "fulfilment_456",
"occurredAt": "2026-07-30T12:25:00.000Z"
}
```
## Memberships
| Event | Sent when | Required `data` fields | Conditional fields |
| - | - | - | - |
| `membership.purchased` | A recurring or one-off membership first activates | `enrollmentId`, `cardId`, `tierId`, `occurredAt` | Recurring purchases include `subscriptionId`; one-off purchases include `billingInterval` |
| `membership.renewed` | A recurring membership advances to a new billing period | `enrollmentId`, `cardId`, `tierId`, `subscriptionId`, `occurredAt` | None |
| `membership.cancelled` | A recurring membership becomes cancelled or incomplete-expired | `enrollmentId`, `cardId`, `subscriptionId`, `occurredAt` | None |
```json theme={null}
{
"enrollmentId": "enr_member_123",
"cardId": "card_member_123",
"tierId": "tier_123",
"subscriptionId": "subscription_123",
"occurredAt": "2026-07-30T13:00:00.000Z"
}
```
```json theme={null}
{
"enrollmentId": "enr_member_123",
"cardId": "card_member_123",
"tierId": "tier_123",
"subscriptionId": "subscription_123",
"occurredAt": "2026-08-30T13:00:00.000Z"
}
```
```json theme={null}
{
"enrollmentId": "enr_member_123",
"cardId": "card_member_123",
"subscriptionId": "subscription_123",
"occurredAt": "2026-09-12T13:00:00.000Z"
}
```
## Engagement
| Event | Sent when | Required `data` fields | Optional `data` fields |
| - | - | - | - |
| `feedback.submitted` | A customer submits card feedback | `enrollmentId`, `cardId`, `rating`, `hasComment`, `occurredAt` | None |
| `automation.fired` | An automated-message firing is recorded | `automationId`, `customerId`, `occurredAt` | None |
| `broadcast.sent` | A wallet broadcast reaches terminal delivery processing | `broadcastId`, `cardId`, `targetCount`, `failureCount`, `occurredAt` | None |
```json theme={null}
{
"enrollmentId": "enr_123",
"cardId": "card_123",
"rating": 5,
"hasComment": true,
"occurredAt": "2026-07-30T14:00:00.000Z"
}
```
```json theme={null}
{
"automationId": "automation_123",
"customerId": "cus_123",
"occurredAt": "2026-07-30T14:05:00.000Z"
}
```
```json theme={null}
{
"broadcastId": "broadcast_123",
"cardId": "card_123",
"targetCount": 250,
"failureCount": 3,
"occurredAt": "2026-07-30T14:10:00.000Z"
}
```
## Bookings
All booking events use the same schema. Only the event name and resulting
`status` differ.
| Event | Resulting `status` |
| - | - |
| `booking.created` | `PENDING` |
| `booking.confirmed` | `CONFIRMED` |
| `booking.attended` | `ATTENDED` |
| `booking.no_show` | `NO_SHOW` |
| `booking.cancelled` | `CANCELLED` |
Required fields are `id`, `provider`, `providerBookingId`, `status`,
`scheduledStart`, `loyaltyCredited`, `source`, and `occurredAt`. The fields
`customerId`, `cardId`, `scheduledEnd`, `attendedAt`, and `resolvedAt` are
nullable. `serviceLabel` and `staffLabel` contain the provider labels saved on
the booking.
Provider lifecycles can skip states. Acuity appointments enter Perkstar as
`CONFIRMED`, normally have no `customerId` until attendance matching runs, and
are auto-attended by the Perkstar scheduler after their end time plus 15
minutes. Acuity does not emit a `PENDING` booking.
```json theme={null}
{
"id": "booking_123",
"provider": "GENERIC_WEBHOOK",
"providerBookingId": "external-booking-123",
"status": "PENDING",
"customerId": null,
"cardId": "card_123",
"serviceLabel": "Consultation",
"staffLabel": "Alex",
"scheduledStart": "2026-08-02T09:00:00.000Z",
"scheduledEnd": "2026-08-02T09:30:00.000Z",
"attendedAt": null,
"resolvedAt": null,
"loyaltyCredited": false,
"source": "adapter",
"occurredAt": "2026-07-30T15:00:00.000Z"
}
```
```json theme={null}
{
"id": "booking_123",
"provider": "ACUITY",
"providerBookingId": "987654",
"status": "CONFIRMED",
"customerId": null,
"cardId": "card_123",
"serviceLabel": "Consultation",
"staffLabel": "Alex",
"scheduledStart": "2026-08-02T09:00:00.000Z",
"scheduledEnd": "2026-08-02T09:30:00.000Z",
"attendedAt": null,
"resolvedAt": null,
"loyaltyCredited": false,
"source": "adapter",
"occurredAt": "2026-07-30T15:05:00.000Z"
}
```
```json theme={null}
{
"id": "booking_123",
"provider": "ACUITY",
"providerBookingId": "987654",
"status": "ATTENDED",
"customerId": "cus_123",
"cardId": "card_123",
"serviceLabel": "Consultation",
"staffLabel": "Alex",
"scheduledStart": "2026-08-02T09:00:00.000Z",
"scheduledEnd": "2026-08-02T09:30:00.000Z",
"attendedAt": "2026-08-02T09:45:00.000Z",
"resolvedAt": null,
"loyaltyCredited": true,
"source": "cron",
"occurredAt": "2026-08-02T09:45:00.000Z"
}
```
```json theme={null}
{
"id": "booking_123",
"provider": "ACUITY",
"providerBookingId": "987654",
"status": "NO_SHOW",
"customerId": "cus_123",
"cardId": "card_123",
"serviceLabel": "Consultation",
"staffLabel": "Alex",
"scheduledStart": "2026-08-02T09:00:00.000Z",
"scheduledEnd": "2026-08-02T09:30:00.000Z",
"attendedAt": "2026-08-02T09:45:00.000Z",
"resolvedAt": "2026-08-02T10:00:00.000Z",
"loyaltyCredited": false,
"source": "adapter",
"occurredAt": "2026-08-02T10:00:00.000Z"
}
```
```json theme={null}
{
"id": "booking_123",
"provider": "ACUITY",
"providerBookingId": "987654",
"status": "CANCELLED",
"customerId": "cus_123",
"cardId": "card_123",
"serviceLabel": "Consultation",
"staffLabel": "Alex",
"scheduledStart": "2026-08-02T09:00:00.000Z",
"scheduledEnd": "2026-08-02T09:30:00.000Z",
"attendedAt": null,
"resolvedAt": "2026-07-31T17:00:00.000Z",
"loyaltyCredited": false,
"source": "adapter",
"occurredAt": "2026-07-31T17:00:00.000Z"
}
```
## Diagnostics
| Event | Sent when | Required `data` fields |
| - | - | - |
| `webhook.test` | An operator sends a test from one webhook's settings | `message`, `webhookId`, `triggeredAt` |
The targeted test ignores the endpoint's subscription filter, but the webhook
must be active.
```json theme={null}
{
"message": "This is a test event from Perkstar.",
"webhookId": "webhook_123",
"triggeredAt": "2026-07-30T16:00:00.000Z"
}
```
# Python SDK
Source: https://developers.perkstar.co.uk/sdks/python
Use the official Perkstar Python client with retries, cursor pagination, typed errors, and webhook verification.
The official synchronous SDK supports Python 3.9 and newer. It covers every
operation in the public v1 API and is suited to Odoo modules, POS middleware,
scheduled syncs, and backend services.
## Install
Install the verified release from PyPI:
```bash theme={null}
python -m pip install "perkstar==0.1.2"
```
The wheel has no compiled extensions, so the same file works on Linux, macOS,
and Windows.
Releases are built and tested in GitHub Actions, published with PyPI Trusted
Publishing, and accompanied by digital attestations. No long-lived PyPI
password or upload token is stored in the repository.
## Create a client
```python theme={null}
import os
from perkstar import Perkstar
with Perkstar(
api_key=os.environ["PERKSTAR_API_KEY"],
user_agent="MyOdooConnector/1.0",
) as perkstar:
context = perkstar.marketplace.ping()
print(context["data"]["organization"]["name"])
```
Pass `oauth_access_token=` instead of `api_key=` when your integration uses
OAuth. Pass exactly one credential type.
## Post a POS transaction
```python theme={null}
result = perkstar.marketplace.accrue(
{
"identifier": {"external_ref": "odoo:4:partner:981"},
"card_id": "card_123",
"transaction": {
"type": "STAMP",
"delta": 1,
"external_transaction_id": "odoo:4:pos_order:94721",
},
},
idempotency_key="odoo:4:pos_order:94721:loyalty",
)
print(result["enrollment"]["balance"])
```
The SDK generates an idempotency key for a new POST and preserves it across
automatic retries. Supply your own stable key when a durable job may restart in
a different process.
## Pagination
```python theme={null}
for customer in perkstar.customers.list(limit=100):
sync_customer(customer)
```
Requests are lazy and follow `next_cursor` until the API reports no more rows.
An empty or repeated cursor stops with an error instead of looping forever.
## Typed errors
```python theme={null}
from perkstar import PerkstarError, PerkstarRateLimitError
try:
post_loyalty()
except PerkstarRateLimitError as error:
schedule_retry(error.retry_after)
except PerkstarError as error:
print(error.code, error.request_id)
```
Network failures, `408`, `429`, and retryable `5xx` responses are retried up to
three times by default. The client honours `Retry-After` and keeps the API error
code, HTTP status, request ID, and API version on the raised exception.
## Verify webhooks
```python theme={null}
from perkstar import verify_webhook_signature
event = verify_webhook_signature(
raw_request_body,
request.headers["X-Perkstar-Signature"],
webhook_secret,
)
```
Pass the exact raw `str` or `bytes` body. The helper uses constant-time HMAC
comparison and rejects timestamps outside a five-minute replay window.
## Verify the hosted fallback
Partners operating in locked-down environments can use the matching
Perkstar-hosted release and checksum:
```bash theme={null}
curl --fail --remote-name \
https://dashboard.perkstar.co.uk/developer-downloads/perkstar-0.1.2-py3-none-any.whl
curl --fail --remote-name \
https://dashboard.perkstar.co.uk/developer-downloads/SHA256SUMS
sha256sum --check SHA256SUMS --ignore-missing
```
The [source distribution](https://dashboard.perkstar.co.uk/developer-downloads/perkstar-0.1.2.tar.gz)
is also available for inspection and local builds.
# TypeScript SDK
Source: https://developers.perkstar.co.uk/sdks/typescript
Use the official typed Perkstar client with automatic retries, pagination, and webhook verification.
The official SDK supports Node.js 18+ and ships ESM and CommonJS builds with no
runtime dependencies.
```bash theme={null}
npm install @perkstar/api-client
```
## Create a client
```ts theme={null}
import { PerkstarClient } from "@perkstar/api-client";
const perkstar = new PerkstarClient({
apiKey: process.env.PERKSTAR_API_KEY!,
userAgent: "MyOdooConnector/1.0",
});
const context = await perkstar.marketplace.ping();
console.log(context.data.organization.name);
```
You can pass an OAuth access token instead of an API key:
```ts theme={null}
const perkstar = new PerkstarClient({
oauthAccessToken: accessToken,
});
```
Pass exactly one credential type.
## Post a POS transaction
```ts theme={null}
const result = await perkstar.marketplace.accrue(
{
identifier: { external_ref: "odoo:4:partner:981" },
card_id: "card_123",
transaction: {
type: "STAMP",
delta: 1,
external_transaction_id: "odoo:4:pos_order:94721",
},
},
{
idempotencyKey: "odoo:4:pos_order:94721:loyalty",
},
);
console.log(result.enrollment.balance);
```
The SDK generates an idempotency key for each new POST call and keeps it across
its automatic retries. Pass your own stable key when a job may restart in a new
process.
## Pagination
```ts theme={null}
for await (const customer of perkstar.customers.list({ limit: 100 })) {
await syncCustomer(customer);
}
```
## Typed errors
```ts theme={null}
import {
PerkstarRateLimitError,
PerkstarValidationError,
} from "@perkstar/api-client";
try {
await postLoyalty();
} catch (error) {
if (error instanceof PerkstarValidationError) {
console.error(error.code, error.requestId);
return;
}
if (error instanceof PerkstarRateLimitError) {
throw error; // let the durable job retry later
}
throw error;
}
```
By default the client retries network errors, `429`, and retryable `5xx`
responses up to three times, honours `Retry-After`, and times out each request
after 30 seconds.
## Verify webhooks
```ts theme={null}
import { verifyWebhookSignature } from "@perkstar/api-client/webhooks";
const event = verifyWebhookSignature({
payload: rawBody,
signature: signatureHeader,
secret: process.env.PERKSTAR_WEBHOOK_SECRET!,
});
```
The helper uses constant-time HMAC comparison and rejects timestamps outside a
five-minute tolerance by default.
The REST API currently contains a few endpoints that are not yet wrapped by
the SDK, including locations and direct wallet pushes. Use the generated API
reference for those calls while keeping the same bearer and retry rules.
# API availability
Source: https://developers.perkstar.co.uk/support/api-availability
See which Perkstar resources are stable public contracts and which workflows are not yet partner-ready.
This matrix is the honest boundary of the public v1 API. A dashboard feature or
internal provider adapter is not automatically a supported public resource.
| Capability | Public status | Supported path |
| - | - | - |
| Customers | Available | List, retrieve, create/upsert, update, and anonymise through `/customers` |
| Enrolments | Available | List, retrieve, create, and update status through `/enrollments` |
| Transactions | Available | List and post loyalty ledger entries through `/transactions` |
| Loyalty cards | Read-only | List and retrieve card configuration through `/cards` |
| Locations | Read-only | List mapped business locations through `/locations` |
| Wallet pushes | Write-only | Send to an enrolment through `/pushes` |
| Outbound webhooks | Available | Configure endpoints through `/webhooks`; receive the [event catalogue](/reference/webhook-events) |
| POS/ERP loyalty | Available | Use `/marketplace/ping`, `/marketplace/accrue`, `/marketplace/enroll`, and `/marketplace/reverse` |
| Rewards and vouchers | Event/workflow access | Observe earning and redemption through enrolments, transactions, and webhooks; no first-class public CRUD resource yet |
| Tiers and benefits | Event/read context | Card and event context is available; tier and benefit management is not a public contract yet |
| Orders | Partner-owned | Send stable external transaction IDs and amounts; Perkstar does not expose a generic order resource |
| Coupons | Redemption events | `coupon.redeemed` is public; coupon catalogue and redemption APIs are not yet public |
## What partner-ready means
Perkstar publishes a resource only after it has:
* an organisation and scope boundary;
* stable identifiers and idempotency rules;
* documented validation, errors, and rate limits;
* test-mode behaviour that cannot alter live data;
* OpenAPI, TypeScript, Python, and Postman parity; and
* webhook or reconciliation behaviour where eventual consistency matters.
Until those conditions are met, use the documented public workflow rather
than calling dashboard actions or internal routes. Internal endpoints can
change without notice and are not covered by the API versioning policy.
## Designing future functionality
For reward, voucher, tier, benefit, coupon, or order requirements that the
matrix does not cover, contact
[support@perkstar.co.uk](mailto:support@perkstar.co.uk) with the provider,
merchant journey, required writes, and reconciliation model. This lets
Perkstar promote a complete contract instead of exposing a fragile partial
endpoint.
# Go-live checklist
Source: https://developers.perkstar.co.uk/support/go-live-checklist
Verify security, correctness, and operational recovery before sending production traffic.
Use this checklist for every integration, even when the first test looked
simple. Loyalty errors are customer-visible and often occur during a busy sale.
## Credentials
* [ ] A new live key exists for this integration only.
* [ ] The key has the minimum scopes required.
* [ ] The secret is stored server-side and is absent from source control and logs.
* [ ] The owner and rotation process are documented.
* [ ] The test key is not used in production.
## Customer and card mapping
* [ ] Upstream customer references are stable and namespaced.
* [ ] Every store or programme maps to an explicit Perkstar `card_id` when several cards exist.
* [ ] Perkstar `locationId` mappings have been checked for every venue.
* [ ] Current opaque and legacy wallet barcode values are passed through unchanged.
* [ ] Consent flags are copied only from an auditable consent source.
## Transactions
* [ ] Every POST has a stable `Idempotency-Key`.
* [ ] POS awards include a permanent `external_transaction_id`.
* [ ] A simulated timeout followed by a retry creates one result.
* [ ] A duplicate upstream webhook creates one result.
* [ ] Full refunds reverse the original transaction.
* [ ] Partial-refund behaviour has been agreed with the business.
* [ ] The card type rejects incompatible transaction types cleanly.
## Failure handling
* [ ] `429` respects `Retry-After`.
* [ ] Network errors and retryable `5xx` responses enter a durable retry queue.
* [ ] Non-retryable `4xx` failures are visible to an operator.
* [ ] Offline operations retain their original stable IDs.
* [ ] Reconciliation can detect an order with no matching Perkstar transaction.
* [ ] Logs retain `X-Request-Id` but never API keys or full personal payloads.
## Webhooks
* [ ] Signatures are verified against the raw body.
* [ ] Event IDs are deduplicated in persistent storage.
* [ ] Test events are separated using `testMode`.
* [ ] Events can arrive more than once or out of order.
* [ ] The receiver acknowledges only after durable storage or processing.
## Launch
1. Process one low-risk live transaction.
2. Confirm the Perkstar ledger and wallet update.
3. Reverse it and confirm both systems.
4. Enable one location or small traffic group.
5. Monitor errors, retries, and reconciliation before widening traffic.
# API status
Source: https://developers.perkstar.co.uk/support/status
Check live Perkstar API, dashboard, scanner, wallet, webhook, billing, and POS service health.
Use the [Perkstar status page](https://dashboard.perkstar.co.uk/status) before
investigating an integration failure. It combines direct dependency checks with
the production synthetic journey that runs across Perkstar services.
View current component health, the latest automated check, 24-hour check
success, and recent affected components.
## Components
| Component | What is checked |
| - | - |
| Public API | Database readiness, cache access, and API health |
| Dashboard | Business sign-in and application availability |
| Scanner | Staff sign-in, scanner loading, and version delivery |
| Wallet services | Apple Wallet pass delivery boundaries |
| Webhooks and billing | Webhook ingestion and Stripe connectivity |
| POS integrations | Scheduled POS synchronization smoke mode |
The page deliberately does not stay silently green when monitoring is late. If
the synthetic run has not completed within its expected window, components show
as degraded until a fresh result arrives.
## Machine-readable status
```bash theme={null}
curl https://dashboard.perkstar.co.uk/api/status
```
The JSON endpoint allows cross-origin GET requests and returns the overall
condition, component conditions, 24-hour success percentages, timestamps, and
recent affected component names. It never exposes internal exception messages
or tenant data.
Include the `X-Request-Id` from a failed API response when contacting support.
The status page identifies broad service health; the request ID lets Perkstar
trace one integration call.
# Versioning and compatibility
Source: https://developers.perkstar.co.uk/support/versioning
Understand Perkstar API versions, SDK releases, and safe upgrade practices.
The REST API is date-versioned. Every response includes `X-API-Version`, and the
OpenAPI document identifies the contract it describes.
## Compatibility policy
Within a published API version, Perkstar may:
* add optional response fields;
* add new endpoints or webhook event types;
* add optional request fields; and
* improve validation and error detail without changing successful behaviour.
Integrations should ignore unknown response fields and webhook event types they
do not handle. Do not model API objects as closed dictionaries unless your
decoder supports forward-compatible fields.
A breaking change requires a new version and a migration period. The current
OpenAPI description states the active deprecation policy.
## SDK versions
`@perkstar/api-client` follows semantic versioning:
* patch releases contain compatible fixes;
* minor releases add compatible functionality; and
* major releases may require code changes or pin a newer API contract.
Pin a supported version range, run contract tests in CI, and review the
[changelog](/changelog) before upgrading.
## Detecting drift
Log `X-API-Version` with request IDs. During deployment, compare the SDK's
exported `API_VERSION` with the server header and alert on an unexpected value.
# Connect with MCP
Source: https://developers.perkstar.co.uk/tools/mcp
Give compatible AI clients secure, read-only access to Perkstar business reporting through OAuth.
Perkstar exposes a Model Context Protocol server for conversational reporting.
The connection is read-only: it can inspect loyalty data and analytics, but it
cannot change customers, balances, cards, messages, or account settings.
## Connection details
| Setting | Value |
| - | - |
| Server URL | `https://dashboard.perkstar.co.uk/api/mcp` |
| Transport | Stateless Streamable HTTP, JSON response mode |
| Authentication | OAuth 2.0 Authorization Code with PKCE |
| Required plan | Growth or above; Perkstar staff access is separate |
| Mutations | None |
Add the server URL to a compatible MCP client. The client discovers Perkstar's
authorization, registration, token, and revocation endpoints automatically.
The business owner or manager signs in, selects the organisation, and approves
the read-only `MCP` scope.
A Perkstar API key cannot access MCP. Use the OAuth flow started by the MCP
client; do not paste a dashboard API key into an AI application.
## Available business tools
Business overview, loyalty-card health, locations, and unusual-activity
summaries.
Search customers, inspect a customer, view behavioural groups, and rank top
customers.
Query stamps, points, redemptions, adjustments, and outstanding rewards.
Performance, feedback, memberships, bookings, referrals, and broadcast
reporting.
The server also provides guided prompts for a weekly performance review,
win-back candidates, and card health checks. Tools return current Perkstar data;
the AI client decides how to explain it.
## Security model
1. OAuth consent pins the token to one Perkstar organisation.
2. The server checks the token scope, expiry, revocation, plan, and consenting
user on every request.
3. Tool schemas reject unknown fields and keep result sizes bounded.
4. Requests appear in the organisation's API activity log and follow its
seven-day API audit retention.
5. Revoking the connection invalidates the access and refresh token pair.
Perkstar staff tools can query across organisations, but they are exposed only
when the consenting user independently passes the Perkstar staff check. A
normal business connection cannot request or smuggle an organisation override.
## Client compatibility
The server supports MCP protocol versions `2025-06-18`, `2025-03-26`, and
`2024-11-05`. It implements `initialize`, `ping`, tool listing and calls, and
prompt listing and retrieval. It does not expose an SSE stream, resources,
sampling, or write tools.
For a bespoke application rather than an MCP client, use the
[marketplace OAuth guide](/guides/oauth-marketplace) and public REST API.
# Run the API in Postman
Source: https://developers.perkstar.co.uk/tools/postman
Import the official Perkstar collection and environment for repeatable, end-to-end API testing.
The official Postman collection is generated from the same OpenAPI contract as
this reference. It contains every public v1 operation, example bodies,
inherited bearer authentication, request tracing checks, and automatic ID
capture for multi-step testing.
This collection is a testing tool, not a second source of API truth. Guides
explain behaviour and the OpenAPI reference defines the contract; the Postman
files make that contract quick to exercise.
In Postman choose **Import → Link** and paste this URL. Requests are grouped
by customers, enrolments, transactions, cards, webhooks, locations, pushes,
and marketplace operations.
Production base URL and safe placeholder variables. It contains no live
credential.
## Import and connect
In Postman, choose **Import → Link** and paste:
```text theme={null}
https://dashboard.perkstar.co.uk/developer-downloads/perkstar-public-api.postman_collection.json
```
Import the environment file from the card above, then select **Perkstar
Production** in the environment menu.
Create a read-only test key in **Dashboard → Settings → API keys**. Replace
the `api_key` environment value with that key and mark the value as secret.
Open **Marketplace → Auth check + org context** and send the request. A
successful response identifies the connected business and available cards.
Run the **Cards** folder first. Collection tests verify the API version,
request ID, and absence of a server error on every response.
## Write requests
POST requests use Postman's `{{$guid}}` dynamic variable for a fresh
`Idempotency-Key`. Replace it with a stable business reference when testing a
job that may be replayed from another process. For a manual retry, keep the
resolved key from the first request instead of generating another one.
The collection includes write and delete requests. A read-only key keeps those
requests safely blocked. Add only the scopes needed for the operation you are
deliberately testing, and use a test key before switching to live.
## Keep it current
The collection and environment are regenerated whenever the canonical API
contract changes. CI rejects a release if the checked-in files are stale or if
their method and path coverage differs from the OpenAPI reference.
## What to run before launch
Run **Marketplace → Auth check + org context**. Confirm the response names
the intended business, reports the expected key mode, and lists the cards
your integration expects.
Run the Cards, Locations, Customers, and Enrolments folders with a read-only
test key. Collection tests verify request IDs and reject unexpected server
errors.
Use a test key and an existing enrolment. Send the same write twice with the
same resolved `Idempotency-Key`; the second response must replay safely
rather than apply loyalty twice.
Create a test endpoint, store the signing secret, send `webhook.test`, and
verify the raw request body before parsing it. Then compare your handler
against the [event catalogue](/reference/webhook-events).