Integrating Your App with Perkville
This guide covers mobile apps and web apps. It focuses on the core concepts, common flows, and caveats that match Perkville’s UI behavior.
App rendering options
Native UI (recommended)
Webview (allowed for mobile)
Core concepts
Business
The top-level container for the loyalty program. Nearly all resources will need this filter. The business ID can be found on the business' Dashboard.
The business object is accessible on the Business resource, filtered by business ID
Location
Locations define where points can be earned and where rewards are redeemable. Each location may have different earning rules, redeeming rules, referral rules, and available challenges. Most, if not all endpoints, will need this filter for accuracy.
Locations are accessible on the Location resource, and filtered by business ID.
If you are making a call from a specific location, you must have a reliable way to map that location to Perkville. You can:
Maintain the mapping on your side and pass the Perkville location ID in API calls.
Add an external location ID to the Perkville location.
The external location ID often crucial to integration functionality. If already populated, consult with the Perkville team before altering this.
If the above does not apply, then we recommend falling back to using the connection's home location or last visited location.
Connection
Represents the customer’s relationship with the business. This will include key information, like the customer's balance, referral offer url, and level (if applicable).
Connections are accessible via the Connection resource, filtered by business ID and user ID.
User ID can be found by fetching the User resource with /users/me or by filtering by email.
Caching (important)
API clients should cache as much as possible. Do not re‑fetch on every screen transition. Only re‑fetch when necessary or when the user manually refreshes.
Recommended behavior:
Load from cache first for core objects (Business, Location, Connection, User) and common views (Earning View, Redeeming View, Vouchers, Challenges).
Re‑fetch only when:
The user manually refreshes
A state‑changing action occurs (join, redeem, earn, voucher used)
The app detects it is working with stale data
Background refresh is optional and should be infrequent.
This keeps the experience fast and minimizes unnecessary API calls
Error handling (important)
The API returns structured validation errors. Clients should handle these gracefully and show customer‑safe messages whenever possible.
Error response format
All errors follow this shape:
error_type: one ofinvalid_request_error,authorization_error,oauth_error,unknown_errorerrors: a dictionary keyed by field name (or__all__), each containing a list of{ code, message }
Recommended behavior
Use the error codes for logic Codes are stable. Use them to decide whether to prompt the user, retry, or block an action.
Show customer‑safe copy The API message is useful for debugging, but may be too technical for end users. Prefer friendly, action‑oriented messages.
Handle field‑level errors If the error is tied to a field, display the message near the corresponding input.
Handle auth errors explicitly If
error_type = oauth_error, prompt the user to re‑authenticate. Iferror_type = authorization_error, block the action and show an access‑related message.Unknown errors For
unknown_error, show a generic message and suggest trying again later. This could either be a temporary server issue or a malformed request.
Example customer‑safe messages
invalid_request_error“We couldn’t complete your request. Please check your details and try again.”authorization_error“You’re not authorized to complete this action.”oauth_error“Your session has expired. Please log in again.”unknown_error“Something went wrong. Please try again later.”
Common flows
View earning rules Use the Earning View endpoint.
View redeeming rules Use the Redeeming View endpoint.
Get vouchers Use the User Voucher View endpoint.
Replicate Perkville’s UI
To match Perkville’s UI, following the guidelines outlined in subsequent pages
Last updated
Was this helpful?

