Skip to main content
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.
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=<id> 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 Save the file, inspect it, then run:
The one-stamp request is:
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 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

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 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:
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. 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.

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 and 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.