Skip to content

REST API Overview

The Appy Stamp REST API is a server-to-server interface for reading and updating loyalty data from your own backend, CRM, or automation tooling. Unlike the JavaScript SDK (which runs in the browser and is scoped to a single logged-in customer), the REST API authenticates as the merchant and can act on any customer in your shop.

The REST and GraphQL APIs expose the same loyalty data and capabilities, so you can pick whichever fits your stack.

https://stamp.appydesign.io/rest_api/v1

All endpoints are under the /rest_api/v1 prefix.

Requests authenticate as the merchant with the X-Api-Key and X-Api-Secret headers. See Authentication for the credentials and how to rotate the secret, and Installation to make your first request.

Every successful response is wrapped in a consistent envelope:

{
"success": true,
"data": { },
"meta": { },
"timestamp": "2026-06-05T12:00:00+00:00"
}
FieldDescription
successtrue for 2xx responses, false for errors
dataThe resource, or an array of resources for list endpoints
metaPresent on list endpoints; holds pagination and count
timestampISO-8601 server time

Fields with null values are omitted from data to keep payloads compact.

Errors use the same envelope with an error object:

{
"success": false,
"error": {
"message": "Customer not found",
"code": "CUSTOMER_NOT_FOUND",
"statusCode": 404
},
"timestamp": "2026-06-05T12:00:00+00:00"
}
CodeHTTPMeaning
UNAUTHORIZED401Missing or invalid API credentials
API_ACCESS_DISABLED403The developer API is not enabled for your store (closed beta)
PLAN_UPGRADE_REQUIRED403The developer API requires a paid plan
VALIDATION_ERROR422Request body failed validation
CUSTOMER_NOT_FOUND404No such customer in your shop
REWARD_NOT_FOUND404No such reward in your shop
EARN_RULE_NOT_FOUND404No such earn rule in your shop
TIER_NOT_FOUND404No such VIP tier in your shop
INSUFFICIENT_STAMPS422Customer does not have enough stamps to redeem
ACTIVITY_NOT_AWARDED422Earn rule could not be awarded (e.g. rate-limited or ineligible)
RATE_LIMITED429Rate limit exceeded
INTERNAL_ERROR500Unexpected server error

List endpoints that can grow large (/customers, /customers/{id}/activities) use cursor-based pagination:

Query paramDescription
limitPage size (default 20, max 1000)
afterCursor for the next page (pass meta.pagination.nextCursor)
beforeCursor for the previous page
hasCountSet to true to include the total count (slower)

The cursor lives in meta.pagination:

{
"success": true,
"data": [ /* ...items... */ ],
"meta": {
"pagination": {
"hasNext": true,
"hasPrevious": false,
"nextCursor": "aWQ6MTAx",
"previousCursor": "aWQ6MQ==",
"count": null
}
},
"timestamp": "2026-06-05T12:00:00+00:00"
}

To walk forward, keep passing the previous response’s nextCursor as after until hasNext is false. Smaller reference lists (/earn-rules, /rewards, /tiers, /beacons, reward codes) are returned in full with a meta.count.

Requests are limited to 1000 per hour per shop. Every response includes:

HeaderDescription
X-RateLimit-LimitYour hourly quota
X-RateLimit-RemainingRequests remaining in the current window

Exceeding the limit returns 429 with the RATE_LIMITED code.

See the Endpoints reference for every resource, or the GraphQL API if you prefer a typed, single-endpoint interface over the same data.