Skip to content

Members reference

Every member endpoint, with full request and response shapes.

All paths are relative to your base URL and require Authorization: Bearer {token}.

MethodPathPurpose
POST/api/v2.0/stores/{storeId}/membersCreate with consent — the webshop signup call
POST/api/v2.0/stores/{storeId}/members/enrollCreate from a phone number, send activation SMS
GET/api/v2.0/stores/{storeId}/members/searchFind by phone, email, identifier, card or activation token
GET/api/v2.0/stores/{storeId}/members/{memberId}Read one member
PUT/api/v2.0/stores/{storeId}/members/{memberId}Update — see what an omitted field does
DELETE/api/v2.0/stores/{storeId}/members/{memberId}Mark for deletion
GET/api/v2.0/stores/{storeId}/members/{memberId}/coupons/Member’s coupons
GET/api/v2.0/stores/{storeId}/members/{memberId}/stamp-cardsMember’s stamp cards
GET/api/v2.0/stores/{storeId}/members/{memberId}/widgets/profileSigned URL for an embeddable profile
POST/api/v2.0/stores/{storeId}/members/{memberId}/reset-phoneStart a phone change
POST/api/v2.0/stores/{storeId}/members/{memberId}/reset-phone-verificationConfirm a phone change
POST/api/v2.0/stores/{storeId}/members/{memberId}/otpSend a one-time code for an action, such as login
POST/api/v2.0/stores/{storeId}/members/{memberId}/otp-verificationVerify a one-time code
GET/POST/api/v2.0/stores/{storeId}/members/{memberId}/dependentsFamily members
GET/api/v2.0/stores/{storeId}/members/{memberId}/invited-friendsReferrals

Returned by create, read, update and search.

{
"id": "m_nsr714RRBEHX",
"first_name": "Ola",
"last_name": "Nordmann",
"email": "ola.nordmann@example.com",
"additional_identifiers": [],
"remarks": null,
"phone": {
"country_code": "+47",
"number": "99900001"
},
"birth_date": "1988-04-12T00:00:00",
"address": {
"street": "Karl Johans gate 3",
"city": "Oslo",
"zip_code": "0154",
"state": null,
"country_code": "NO"
},
"gender": "NotShared",
"consent": {
"gdpr_accepted": true,
"save_order_history": true,
"receive_sms": true,
"receive_email": false
},
"membership_detail": {
"points": 250.0,
"qualification_points": 340.0,
"pending_points": 0.0,
"remaining_points": 160.0,
"level_title": "Gold",
"next_level_title": "Platinum",
"next_level_points": 500.0,
"level_expire_date": "2027-06-16T00:00:00"
},
"department_ids": ["101"],
"segments": [
{
"id": 633,
"text": "What are you interested in?",
"type": "Checkbox",
"is_visible_to_follower": true,
"is_required": false,
"value": null,
"selected_options": [4101, 4103]
}
]
}
FieldNotes
idThe member id. Opaque, case-sensitive
genderMale, Female, NotShared, NonBinary
consentAll four booleans always present on responses
membership_detail.pointsThe balance — show this one. See Points
segments[].idThe segment id. Sent back as segment_id — see Update a member
additional_identifiersDeprecated. Use the identifiers endpoints

POST /api/v2.0/stores/{storeId}/members

The webshop signup call, for when consent has already been collected on your form. Returns 200 with the created member.

{
"phone": { "country_code": "+47", "number": "99900001" },
"first_name": "Ola",
"last_name": "Nordmann",
"email": "ola.nordmann@example.com",
"birth_date": "1988-04-12T00:00:00",
"gender": "NotShared",
"address": {
"street": "Karl Johans gate 3",
"city": "Oslo",
"zip_code": "0154",
"state": null,
"country_code": "NO"
},
"department_ids": ["101"],
"consent": {
"gdpr_accepted": true,
"save_order_history": true,
"receive_sms": true,
"receive_email": false
},
"segments": [
{ "segment_id": 633, "selected_options": [4101] }
],
"origin": {
"system_id": "my-webshop",
"employee_id": null,
"department_id": "101",
"channel": "OnlineStore"
}
}
FieldRequiredNotes
phoneYescountry_code is a dial code (+47)
first_name, last_nameValidated non-empty
emailValidated as an address when present
consentYesgdpr_accepted must be true
consent.receive_sms, consent.receive_emailSend bothLeft out, each takes the value of gdpr_accepted — that is, true
address.country_codeISO alpha-2Rejected if not a real code
department_idsArray of strings
origin.channelSet to "OnlineStore"See the one field everyone forgets
password, repeat_passwordOptional, write-onlyMin 8, max 64, uppercase + numbers

The endpoint sends a welcome SMS, or a welcome email if the store has no SMS configured.


POST /api/v2.0/stores/{storeId}/members/enroll

Creates a member from a phone number and sends an activation link by SMS. The member is not active until they accept.

{
"phone": { "country_code": "+47", "number": "99900001" },
"department_id": "101",
"origin": {
"system_id": "my-webshop",
"department_id": "101",
"channel": "OnlineStore"
},
"additional_info": {
"first_name": "Ola",
"last_name": "Nordmann",
"email": "ola.nordmann@example.com"
}
}

phone and department_id are required. additional_info is optional.

If the member already exists and has not yet accepted, we send a fresh activation link — which makes this safe to call as a “resend”.


GET /api/v2.0/stores/{storeId}/members/search?phone=%2B4799900001
ParameterNotes
phoneInternational format (+47… or 0047…). National format assumes the store’s country
email
identifierValueYour own customer id, if configured
cardIdentifierThe card identifier linked to the member
activationTokenFor completing an in-store signup

At least one is required. Returns an array of members for every parameter, including activationToken.

[ { "id": "m_nsr714RRBEHX", "first_name": "Ola", "...": "..." } ]
SituationResponse
Found200 with a one-element array
Not found200 with []
No parameter given400, naming the parameters you can send
Malformed email400 “Email is not valid”
Malformed phone400 “Phone number is not valid”

GET /api/v2.0/stores/{storeId}/members/{memberId}

Returns the member object. Call this to refresh points and level before rendering a loyalty panel.


PUT /api/v2.0/stores/{storeId}/members/{memberId}

Same body as create, with no phone field. See changing a phone number.

PUT is neither a full replace nor a patch. What happens to a field you leave out depends on the field:

Left out of the bodyResult
first_name, last_name, email, birth_date, genderKept — the current value stays
address, department_ids, segmentsCleared
consent.receive_sms, consent.receive_emailSet to false — the member is unsubscribed from that channel

Segments come back from GET in the read shape — id, text, type and the rest. PUT takes the write shape, keyed by segment_id. Sending the read shape back unchanged returns:

Segment ids are duplicated.

Map them before you send:

const segments = current.segments.map(s =>
s.type === 'Text' || s.type === 'DateTime'
? { segment_id: s.id, value: s.value }
: { segment_id: s.id, selected_options: s.selected_options }
);

The full read-modify-write is in Keeping profiles in sync.

gdpr_accepted: false returns 400:

The 'gdpr_accepted' property on the 'Consent' object must be set to true.
If your goal is to delete the member, please use the DELETE endpoint.

DELETE /api/v2.0/stores/{storeId}/members/{memberId}
{ "is_ok": true, "details": "" }

This is the correct response to a GDPR erasure request, and the correct response to a customer withdrawing consent entirely.

Clear diller_member_id on your own customer record at the same time.


The phone number is the member’s identity, so changing it is a verified, two-step flow rather than a field update.

sequenceDiagram autonumber actor C as Customer participant S as Your server participant D as Diller C->>S: Requests new number S->>D: POST /members/{id}/reset-phone<br/>{ country_code, number } D-->>C: SMS with a code D-->>S: { is_ok: true } C->>S: Enters the code S->>D: POST /members/{id}/reset-phone-verification<br/>{ phone, otp_code } alt Correct D-->>S: { is_ok: true } S-->>C: Number updated else Wrong D-->>S: { is_ok: false, details: "..." } S-->>C: Try again end
POST /api/v2.0/stores/{storeId}/members/{memberId}/reset-phone
{ "country_code": "+47", "number": "99900002" }
POST /api/v2.0/stores/{storeId}/members/{memberId}/reset-phone-verification
{
"phone": { "country_code": "+47", "number": "99900002" },
"otp_code": 123456
}

If you want customers to reach their loyalty profile without a password.

POST /api/v2.0/stores/{storeId}/members/{memberId}/otp
{ "action": "login" }

Sends a code by SMS. Sending is all this call does — it does not log anyone in or change anything.

POST /api/v2.0/stores/{storeId}/members/{memberId}/otp-verification
{ "otp_code": 123456, "action": "login" }
{ "is_ok": true, "details": "" }

The action must match the one you sent the code for.


Rather than building loyalty pages yourself, you can embed ours.

GET /api/v2.0/stores/{storeId}/members/{memberId}/widgets/profile
{ "details_url": "https://diller.app/member/widgets/profile/?token=..." }

Put that URL in an iframe.

A quick way to give a merchant a working “My loyalty” page on day one, while you build something bespoke later.


Family members attached to a membership, where the merchant has enabled it.

GET /api/v2.0/stores/{storeId}/members/{memberId}/dependents
POST /api/v2.0/stores/{storeId}/members/{memberId}/dependents
[
{ "id": 0, "name": "Kari", "birthdate": "2015-06-01", "gender": "Female" },
{ "id": 77, "name": "Jonas", "birthdate": "2018-02-14", "gender": "Male" }
]

POST replaces the whole collection:

  • add — include with "id": 0
  • update — include the complete object with its real id
  • delete — leave it out of the array

Returns 204. name is limited to 50 characters. If a birth date’s day or month is unknown, use 1.


GET /api/v2.0/stores/{storeId}/members/{memberId}/invited-friends
GET /api/v2.0/stores/{storeId}/members/{memberId}/invited-friend?invitationToken={token}
[
{
"first_name": "Kari",
"last_name": "Nordmann",
"email": "kari@example.com",
"created_at": "2026-08-01T09:12:00",
"is_accepted": true,
"points": 50
}
]

Available when the store has friend_referral_enabled: true.