> 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/joining-the-loyalty-program.md).

# Joining the loyalty program

### Fetch Connection

Fetch the Connection for the current customer. You can filter by their user ID (fetched from the [User endpoint](https://www.perkville.com/developers/docs/v2/#v2_resource_28_anchor)) or filter by their email.

```http
curl "https://api.perkville.com/v2/connections/?business=25&user_id=1234" -H "Authorization: Bearer accesstoken123abc"
```

```http
curl "https://api.perkville.com/v2/connections/?business=25&user__emails__email=example@example.com" -H "Authorization: Bearer accesstoken123abc"
```

If the connection exists, you may proceed to the next step and check for necessary [Agreements](#agreements).&#x20;

If the connection doesn't not exist, and you are using an admin-level token, see [creating a connection](#create-a-connection-admin-only).

### Accept Agreements

Businesses can set [Agreements](/features/settings/advanced/agreements.md) that must be agreed to prior to joining the loyalty program. If these restrictions are in place, you'll need to perform a few additional steps before attempting to join on the user's behalf.

[Fetch Agreements](https://www.perkville.com/developers/docs/v2/#v2_rewards_program_user_agreements_view_anchor) that are applicable to joining the loyalty program, and present them to the user.&#x20;

```http
curl "https://api.perkville.com/v2/agreements-view/?business=25&user_id=1234&apply_to_join_flow=true" -H "Authorization: Bearer accesstoken123abc"
```

{% hint style="info" %}
The text field may have hyperlinks in the form of `[this is a link](https://example.com)` so you will want to care when rendering this text field.
{% endhint %}

Once the user agrees to the terms, post the acceptance via the [batch agreement endpoint](https://www.perkville.com/developers/docs/v2/#v2_batch_2_anchor).

Finally, join via the [Connections endpoint](https://www.perkville.com/developers/docs/v2/#v2_resource_7_anchor).

### Create a Connection (admin only)

{% hint style="warning" %}
Only access tokens that have `ADMIN_CUSTOMER_INFO` scopes and are [Admin staff at the business](/features/settings/staff-members.md#staff-member-roles) may create a new connection at this time.
{% endhint %}

If the connection does not exist, you can create an [External Member](/features/customers/customer-identifiers.md#external-member-id) record for this user. To do so, you'll need to `POST` to the [External Member endpoint](https://www.perkville.com/developers/docs/v2/#v2_resource_14_anchor). You'll want to provide key details, like `external_system_id`, `external_member_id`, and the `user_email`.

* &#x20;`external_system_id` should represent what system this is coming from, like `MY_MEMBERSHIP_SYS`.
* `external_member_id` should be a unique ID representing the user in the source system. This will be used moving forward to detect membership/email updates, so make sure it's unique to this individual.
* `user_email` will be the user's email

{% hint style="warning" %}
If Perkville is integrated with the source system, make sure the `external_system_id` and `external_member_id` values match the existing format of the Perkville integration. This will help prevent duplicate external member records from being created.

Please reach out to <support@perkville.com> for clarification on how these IDs are formatted.
{% endhint %}

The `POST` response will include the user's Connection URI. However, before attempting to join on their behalf, you'll want to see if the business has applicable [agreements](#agreements).

Once they have accepted any necessary agreements, you can use the [Connections endpoint](https://www.perkville.com/developers/docs/v2/#v2_resource_7_anchor) to facilitate a customer joining the loyalty program. You would change the Connection status to Active.

### Caveats

1. `status` only accepts **ACTIVE** or **INACTIVE**.
2. Scope rules apply. With `USER_CUSTOMER_INFO`, a user can only update their own Connection. With `ADMIN_CUSTOMER_INFO`, staff can update Connections for their business.

### Validation errors (customer-safe copy)

Below are the join-related validation errors that may be returned when setting `status=ACTIVE`, plus recommended customer-safe messages.

* `pv_connection_membership_not_active`

  When: The business requires an active membership and the customer’s membership is not active.\
  Customer-safe: “Your membership is not active. Please contact the business for help.”
* `pv_agreement_required`\
  When: The business requires agreement terms and the customer has not agreed. They will need to review accept the business' loyalty program terms before being able to join. You can update your application to [accept these agreements in your app](#agreements), or prompt them to join online.\
  Customer-safe: “Please review and accept the required terms to join at {business.perkville\_url}"


---

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

```
GET https://docs.perkville.com/overview/integrations/integrating-perkville/integrating-your-app-with-perkville/joining-the-loyalty-program.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
