> For the complete documentation index, see [llms.txt](https://docs.perkville.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.perkville.com/overview/integrations/integrating-perkville/integrating-your-app-with-perkville.md).

# 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](https://www.perkville.com/developers/docs/v2/#v2_resource_1_anchor), filtered by business ID

#### Location

Locations define where points can be earned and where rewards are redeemable. Each location may have different [earning](/features/earning-rules.md) rules, [redeeming](/features/redeeming-rules.md) rules, [referral](/features/referrals.md) rules, and available challenges. Most, if not all endpoints, will need this filter for accuracy.

Locations are accessible on the [Location resource](https://www.perkville.com/developers/docs/v2/#v2_resource_18_anchor), 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:

1. Maintain the mapping on your side and pass the Perkville location ID in API calls.
2. Add an external location ID to the Perkville [location](/features/settings/locations.md#optional-fields).

{% hint style="warning" %}
The external location ID often crucial to integration functionality. If already populated, consult with the Perkville team before altering this.
{% endhint %}

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](https://www.perkville.com/developers/docs/v2/#v2_resource_7_anchor), filtered by business ID and user ID.

{% hint style="info" %}
User ID can be found by fetching the [User resource](https://www.perkville.com/developers/docs/v2/#v2_resource_26_anchor) with `/users/me` or by filtering by email.
{% endhint %}

#### 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 of `invalid_request_error`, `authorization_error`, `oauth_error`, `unknown_error`
* `errors`: a dictionary keyed by field name (or `__all__`), each containing a list of `{ code, message }`

#### Recommended behavior

1. **Use the error codes for logic**\
   Codes are stable. Use them to decide whether to prompt the user, retry, or block an action.
2. **Show customer‑safe copy**\
   The API message is useful for debugging, but may be too technical for end users.\
   Prefer friendly, action‑oriented messages.
3. **Handle field‑level errors**\
   If the error is tied to a field, display the message near the corresponding input.
4. **Handle auth errors explicitly**\
   If `error_type = oauth_error`, prompt the user to re‑authenticate.\
   If `error_type = authorization_error`, block the action and show an access‑related message.
5. **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.”

### Replicate Perkville’s UI

To match Perkville’s UI, following the guidelines outlined in subsequent pages


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.perkville.com/overview/integrations/integrating-perkville/integrating-your-app-with-perkville.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
