Orishare
Loyalty guides

Points transfer

Let customers gift points to each other, or move points between customers from your backend, with per currency limits.

A transfer moves points of one currency from one customer to another in a single step: the sender is debited and the receiver credited together, or nothing happens. Both sides see it in their ledger history, and the notifications engine receives points.transfer_sent and points.transfer_received.

1. Choose which currencies can move

Only a currency whose capabilities say transferable: true can be transferred. Set it when you create the currency:

curl -X POST "$ORISHARE_API/v1/currencies" -H "Authorization: Bearer $SECRET_KEY" \
  -H "Idempotency-Key: gems-currency" -H "Content-Type: application/json" \
  -d '{"code":"gems","name":"Gems","capabilities":{"schema":"orishare.currency-capabilities/v1",
       "spendable":true,"transferable":true,"qualification":"earned","expiry":{"type":"none"}}}'

Then set its limits, and opt it in for customers if they may transfer it themselves:

curl -X POST "$ORISHARE_API/v1/currencies/gems/transfer_limits" \
  -H "Authorization: Bearer $SECRET_KEY" -H "Idempotency-Key: gems-limits-1" \
  -H "Content-Type: application/json" \
  -d '{"min_amount":100,"max_amount":5000,"daily_max":10000,"customer_enabled":true}'
LimitMeaning
min_amountSmallest transfer (default 1).
max_amountLargest single transfer (default none).
daily_maxMost one sender may transfer of this currency in any 24 hours (default none).
customer_enabledCustomers may transfer this currency from a customer session (default false).

GET /v1/currencies/{id}/transfer_limits (the currency id or its code, here gems) shows the limits in force.

2. Transfer from your backend

curl -X POST "$ORISHARE_API/v1/customers/user_42/transfers" \
  -H "Authorization: Bearer $SECRET_KEY" -H "Idempotency-Key: gift-7781" \
  -H "Content-Type: application/json" \
  -d '{"recipient":{"external_id":"user_77"},"currency":"gems","amount":250,"note":"Thanks!"}'

Name the recipient with exactly one of customer_id, external_id or referral_code (the customer's share code). The response is the transfer (xfr_...) with both ledger entry ids. Sending the same request again with the same Idempotency-Key returns the same transfer and moves nothing; the same key with a different body is refused with idempotency_key_reused.

Read transfers with GET /v1/customers/{id}/transfers (sent and received, newest first) and GET /v1/points_transfers/{id}.

3. Let customers transfer

From your app or the hosted portal, with a customer session:

curl -X POST "$ORISHARE_API/v1/customer/transfers" \
  -H "Authorization: Bearer $PUBLISHABLE_KEY" -H "X-Orishare-Customer-Token: $CUSTOMER_TOKEN" \
  -H "Idempotency-Key: 6f1c2b" -H "Content-Type: application/json" \
  -d '{"recipient":{"referral_code":"FRIEND-42"},"currency":"gems","amount":100}'

A customer names the recipient by external_id or referral_code only, and the answer never shows the recipient's internal id.

What is refused

CaseError
Sender and recipient are the same customer, including two profiles merged into onevalidation_failed (400)
Amount below min_amount or above max_amountvalidation_failed (400)
Recipient not foundresource_not_found (404)
Currency not transferable, or not opted in for customersinvalid_state (409)
Anonymous or deleted sender or recipientinvalid_state (409)
Not enough pointsinsufficient_balance (409)
Over the sender's daily_max for the last 24 hoursquota_exceeded (429)

Billing

A transfer is one billable operation, the same as a manual ledger adjustment (POST /v1/ledger_entries): the credit to the receiver is part of it, and a replayed request is not billed again.

Merged customers

Transfers work on the customer as a whole: a profile merged into another sends from and receives into the surviving customer's balance, and the transfer records the surviving customer.

On this page