# Member cards (Secutix contacts)

The Secutix connector isn’t limited to event tickets. It can also sync **Secutix contacts**. This unlocks a “member card in wallet” flow. The pass represents the contact and stays in sync.

## What you can build

You can issue a wallet pass that behaves like a membership card:

* One pass per member (one Secutix contact).
* Barcode / QR code for identification at the venue.
* Automatic updates when contact data changes.
* Optional install/uninstall feedback written back to Secutix.

{% hint style="info" %}
Secutix stays the source of truth for the member profile. Wallet Crew issues and distributes the pass.
{% endhint %}

<details>

<summary>Real-world use cases</summary>

Patterns that work well in production:

* **Membership renewal at the venue**: scan a QR code, update the contact, refresh the pass.
* **Self-service registration**: members sign up from a campaign landing page.
* **Staff-assisted sign-up**: front-office teams use a form instead of Secutix UI.
* **Consent capture**: store opt-in criteria in Secutix during enrolment.
* **Segmented messaging**: use install status to target installed members only.

</details>

## Create and update contacts from an enrolment form

Use a Wallet Crew **enrolment form** to:

* Create a new Secutix contact.
* Update an existing Secutix contact.
* Immediately deliver the member card to Apple Wallet / Google Wallet.

This works well when you don’t want to expose Secutix UI to staff. It also fits self-service registration flows.

### QR code entry point

Display a QR code that opens the enrolment form on a phone. This is ideal for on-site acquisition. Think foyer, ticket desk, or partner booths.

### Mapping: Wallet Crew account ↔ Secutix contact

When contact sync is enabled, Wallet Crew maps **account fields** to **Secutix contact fields**. Customize the mapping when you need to read/write specific Secutix criteria. This is common for consents, segmentation flags, or legacy fields.

Add your custom mapping script in the Secutix configuration **Advanced** tab.

<p align="center"><a href="https://admin.thewalletcrew.io/tenant/~/integrations/secutix/settings" class="button secondary" data-icon="chevrons-right">Secutix configuration screen</a></p>

#### Advanced contact mapping hook

Register `extensions.secutix.contact.mapper`.

* `MapToSecutix(account, request)` runs **before** calling Secutix.
* `MapToNeostore(response, account)` runs **after** Secutix responds.

```javascript
/**
 * Applies enhanced mapping from neostore account data to a Secutix contact request.
 * The standard mapping is already applied on the request object before this function is called.
 *
 * @param {Object} account - Data coming from neostore.
 * @param {Object} request - Request sent to Secutix with default mapping already populated.
 */
function mapToSecutix(account, request){
  request.ExternalContactCriterionData = [{ CriterionIdCode : 'OPT_CO', Values : [account["consents_email"] ? 'true' : 'false'] }];
}

/**
 * Applies enhanced mapping from a Secutix contact response back to a neostore account.
 * The standard mapping is already applied on the account object before this function is called.
 *
 * @param {Object} response - Response received from Secutix.
 * @param {Object} account - Data sent to neostore with default mapping already populated.
 */
function mapToNeostore(response, account){
  response.ContactCriteria = response.ContactCriteria || [];
  account["consents_email"] = !!response.ContactCriteria.find(c => c.CriterionIdCode === 'OPT_CO' && c.Values != null && c.Values[0] === 'true');
}

export default function(context) {
  context.register('extensions.secutix.contact.mapper', {
    MapToSecutix : mapToSecutix,
    MapToNeostore: mapToNeostore
  });
}
```

#### Installation status update on contact

This hook lets you persist pass install/uninstall signals into Secutix contact criteria. Use it to drive segmentation or operational reporting in Secutix.

Implement `extensions.secutix.contact.passUpdater`:

```javascript
/**
 * Triggered when a member card installation status changes.
 *
 * @param {Object} request - Secutix SaveIndividualContactRequest.
 * @param {boolean} isInstalled - `true` if the card is installed, otherwise `false`.
 * @param {number} device - Device on which the installation status changed (0 = Apple, 2 = Google).
 * @returns {Promise<void>} No return value; modifies the request in place.
 */
async function onPassInstallationStatusChanged(request, isInstalled, device){
  request.ExternalContactCriterionData = [
    {
      CriterionIdCode : 'W_' + (device == 0 ? "APPLE" : "GOOGLE"),
      Values : [isInstalled ? 'Installé' : 'Désinstallé']
    }
  ];
}

export default function(context) {
  context.register('extensions.secutix.contact.passUpdater', {
    OnPassInstallationStatusChanged: onPassInstallationStatusChanged
  });
}
```


---

# Agent Instructions: 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.thewalletcrew.io/connect/ticketing/secutix/member-cards-secutix-contacts.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.
