> ## Documentation Index
> Fetch the complete documentation index at: https://developers.perkstar.co.uk/llms.txt
> Use this file to discover all available pages before exploring further.

# Build a POS integration

> Connect a till to Perkstar with safe customer matching, loyalty accrual, and refunds.

The marketplace endpoints are the shortest path for a POS integration. One
request can resolve a customer, choose a card, find or create the enrolment, and
post the loyalty transaction.

## 1. Create a dedicated key

Create one API key per POS connection. Grant:

* `MARKETPLACE` for ping, accrue, enrol, and reverse;
* `LOCATIONS_READ` when transactions must be attributed to a store; and
* read scopes only when the adapter genuinely needs separate reconciliation.

Use a test key during development and a new live key for production.

## 2. Confirm the business and cards

```bash theme={null}
curl "$PERKSTAR_API_URL/marketplace/ping" \
  --header "Authorization: Bearer $PERKSTAR_API_KEY"
```

When `default_card_id` is null, the business has more than one active card. Ask
the operator to map each POS location or loyalty programme to a specific
`card_id`; never guess the first card.

## 3. Identify the customer

Send at least one identifier. Perkstar checks them in this order:

1. `card_serial`
2. provider identity for first-party integrations
3. `external_ref`
4. email
5. phone

For a wallet scan, pass the barcode content unchanged as `card_serial`. Current
opaque POS identifiers and older numeric or serial formats are both resolved by
the API. Do not parse, reformat, truncate, or assume a fixed length.

For customer records coming from the POS, prefer a namespaced stable ID:

```json theme={null}
{
  "identifier": {
    "external_ref": "odoo:company_4:partner_981"
  }
}
```

## 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" }
    }
  }'
```

For points based on spend, send `type: "POINTS"` with `amount_pence`. Perkstar
uses the card's points rule. Send an explicit `delta` only when the upstream
system is authoritative for the points amount.

## 5. Handle refunds

```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"
  }'
```

Do not create a negative award as a substitute for reversal. The reversal links
the audit trail to the original transaction and preserves retry safety.

## Production rules

* A sale callback must acknowledge only after Perkstar has accepted or durably queued the operation.
* Retry timeouts and `5xx` responses with the same IDs.
* Respect `Retry-After` on `429`.
* Queue offline work locally and retain the original transaction time and ID.
* Show terminal failures to staff; do not drop them silently.
* Keep location mapping explicit when the business has several stores.

<Note>
  A test marketplace call cannot create a live customer or enrolment. Prepare an
  existing test customer/card enrolment before testing accrual.
</Note>


## Related topics

- [Perkstar developer platform](/index.md)
- [Connect Odoo](/guides/odoo.md)
- [Idempotency and retries](/fundamentals/idempotency.md)
- [API status](/support/status.md)
- [Test mode](/fundamentals/test-mode.md)
