Skip to main content

Tip-Recipient Linking

The tip-recipient linking flow lets a staff member connect their OpenApp account to an identifier from the POS. The Merchant API calls this identifier externalTipRecipientId. Payment messages and receipt QR codes use the shorter name tipRecipientId for the same value.

After the staff member confirms the link in OpenApp and passes KYC, the record becomes ACTIVE. Tips attributed to its externalTipRecipientId are then routed to the staff member's OpenApp wallet. If the record does not exist or is not active, tips go to merchant settlement.

The POS is responsible for collecting the phone number a staff member wants to link. How the POS presents this to the user is its own concern.

Endpoints used in this flow:

EndpointDirectionPurpose
GET /merchant/v1/tipRecipientsPOS -> OpenAppRetrieve all tip-recipient records in the merchant and integration-profile scope associated with the API credential.
GET /merchant/v1/tipRecipients/{id}POS -> OpenAppRetrieve the record whose externalTipRecipientId equals {id}.
PUT /merchant/v1/tipRecipients/{id}POS -> OpenAppUpsert a record and, when needed, start account linking. Request body: PutTipRecipientRequest. Response: LinkTipRecipientResponse.

All three endpoints use Merchant API HMAC authentication. OpenApp derives the merchant and integration-profile scope from the API credential; the POS does not send either identifier in the request.

Identifiers​

Each record has two identifiers:

  • externalTipRecipientId is the stable identifier supplied by the POS as the {id} path parameter. Payment messages and receipt QR codes refer to this value as tipRecipientId.
  • id is an OpenApp-generated identifier returned in the API response. The OpenApp app uses it during confirmation. The POS should continue to address the record by externalTipRecipientId.

Reading the roster​

The POS may fetch the current roster at any time to populate a staff picker or verify records.

GET /merchant/v1/tipRecipients returns an array of TipRecipient records.

GET /merchant/v1/tipRecipients/{id} returns one TipRecipient, or HTTP 404 if the externalTipRecipientId does not exist in the credential's scope.

Linking submission​

The POS sends PUT /merchant/v1/tipRecipients/{id} with the staff member's phone number and display name. OpenApp normalizes the phone number and applies the following rules:

Current recordResult
No recordOpenApp creates a PENDING record with a three-day confirmation period.
PENDINGOpenApp updates the phone number and display name and restarts the three-day confirmation period.
ACTIVEOpenApp removes the current user association, changes the record to PENDING, and starts a new three-day confirmation period.

The response always contains the resulting record in LinkTipRecipientResponse.tipRecipient. Validation failures use standard HTTP error responses rather than a flow-specific success/failure result.

See PutTipRecipientRequest for the full request body reference.

Confirmation and status​

For a PENDING record, OpenApp notifies the staff member when an OpenApp account already exists for the submitted phone number. The staff member confirms the link in the OpenApp app. Confirmation requires the same phone number and an account that passes the OpenApp KYC requirement.

The POS can poll either GET endpoint and inspect linkStatus. When the status is PENDING, expiresAt gives the confirmation deadline. OpenApp rejects confirmation after that deadline. Removal of the expired record is asynchronous, so GET may briefly return an expired PENDING record. Submit another PUT to restart the process.

See Link status for the full status vocabulary.

note

There is no POS-side unlink endpoint. Submitting a different phone number for an active record replaces the current association with a new pending link.