Going live
Environments
Section titled “Environments”| Sandbox (prerelease) | Production | |
|---|---|---|
| Base URL | https://api.prerelease.dillerapp.com | https://api.diller.app |
| Token endpoint | …/connect/token | …/connect/token |
| Credentials | Sandbox only | Production only |
| Data | Disposable | Real customers |
| SMS | May be disabled | Real messages to real phones |
Credentials are not interchangeable. A sandbox client id will not authenticate against production, and vice versa.
Put the base URL in configuration, never in code. The only difference between your sandbox and production build should be four values: base URL, client id, client secret, store id.
DILLER_BASE_URL=https://api.prerelease.dillerapp.comDILLER_CLIENT_ID=...DILLER_CLIENT_SECRET=...DILLER_STORE_ID=...The store id differs per environment too. Read it from
GET /api/v2.0/stores once for each environment and pin it in
configuration.
Getting credentials
Section titled “Getting credentials”Production credentials belong to the merchant. They find them in their Diller account:
Settings → Our Details → API Details
That page shows the token endpoint, the flow, the scopes, the client id and the client secret. Ask the merchant to send you both over something safer than email — a password manager share, or your usual secrets channel.
Sandbox credentials come from us. Ask for a prerelease store when you start the integration, not the week you plan to launch.
Pre-launch checklist
Section titled “Pre-launch checklist”Authentication
Section titled “Authentication”- Base URL, client id, secret and store id all come from configuration
- Token is cached and reused, not fetched per request
-
401triggers exactly one refresh-and-retry - Secret is in a secrets manager, not the repository
- Nothing Diller-related is reachable from client-side JavaScript
- Store id is used verbatim, with no case transformation
Members
Section titled “Members”- Search before create, every time
- Empty-array miss handled, not just the HTTP status
-
400“already registered” recovers by searching and updating -
consent.gdpr_acceptedcomes from a real ticked checkbox -
receive_smsandreceive_emailsent on every create and update, each from its own unticked checkbox - Merchant’s terms shown,
privacy_policy_urllinked -
PUTbuilt from a fresh read — address, departments, segments (assegment_id) and both marketing flags -
diller_member_idstored on your customer record - No silent enrolment on login
- Segment form rendered from
GET /segments - Phone changes go through
reset-phone, notPUT
Orders
Section titled “Orders”-
origin.channelis"OnlineStore"on every call that takes an origin -
external_idis deterministic —ORDER-{id}, no timestamps -
origin.department_idandorigin.system_idfixed, so a retry is caught as a duplicate -
is_okchecked on every transaction response -
created_atcarries an explicit UTC offset, and seconds -
totalmatches the sum ofpayment_details - Line
total_price=quantity x unit_price - discount - Cancel and refund paths implemented and tested
- Transaction posted after payment capture, not before
Coupons
Section titled “Coupons”- Validate on apply and again before payment
- Reserve immediately before payment
-
cancel-reservationon payment failure - Reservations from abandoned carts released by a scheduled sweep
- Coupons addressed by
code, never by id -
times_redeemedrespected againstmax_redemptions, and unlimited coupons shown without a count
Resilience
Section titled “Resilience”- Short timeouts on cart-path calls
- Loyalty failure never blocks a purchase
- Failed transaction posts are queued, not dropped
- Backoff with jitter on
5xx; no retry on4xx - Requests and responses logged against the order id
Privacy
Section titled “Privacy”- Only data the customer consented to is sent
-
DELETEwired to your erasure process - Loyalty data authorised against the session, never a browser-supplied member id
- Logs do not contain access tokens
Testing before launch
Section titled “Testing before launch”Run these against sandbox and confirm each one.
| Scenario | Expected |
|---|---|
| New customer signs up | Member created, id stored |
| Existing member signs up again | Found by search, updated — no “already registered” error surfaced |
| Customer logs in, already linked | No Diller write |
| Customer logs in, not a member | Offer shown; nothing created |
| Signup with consent unticked | No member created |
| Signup with the SMS box ticked, email unticked | receive_sms: true, receive_email: false on the member |
| Profile edited | Address, departments, segments and both marketing flags survive the PUT |
| Order with no coupon | Points awarded |
| Order with a coupon | Discount applied, redemption recorded, reservation released |
| Payment fails after reserve | Reservation released; coupon usable again |
| Cart abandoned after reserve | Sweep releases the reservation; coupon usable again |
| Order cancelled | Points and coupon reversed |
| Partial refund | Points adjusted |
| Same order posted twice | Second post returns is_ok: false; only one transaction |
| Diller unreachable at checkout | Purchase still completes |
| Erasure requested | DELETE sent, local id cleared |
Test the coupon-release paths deliberately — force a payment failure, and abandon a cart at the payment step. They are the ones that silently destroy customer value if they are wrong, and the ones least likely to be exercised by accident.
Cutover
Section titled “Cutover”- Get production credentials from the merchant.
- Change the four configuration values above. Nothing else.
- Confirm the token call succeeds against
api.diller.app. - Confirm
GET /stores/{storeId}returns the right store — check the name, not just the status code. - Put one real order through, end to end, with a real phone number you control. Production sends real SMS.
- Verify in the merchant’s Diller account that the member and transaction appear, in the right department and the right channel.
- Then open it up.
Do not migrate historical orders on day one. Get today’s flow correct first; backfill later, throttled, and after talking to us.
After launch
Section titled “After launch”Watch, for the first fortnight:
- Members created per day — a sudden zero means signup is broken
- Transactions posted vs orders placed — the gap is your failure rate
4xxrate by endpoint- Queue depth for failed transaction posts
- Open reservations older than your sweep age — this should stay at zero. Each one is a coupon a customer can no longer use
That last one is worth an alert. It is invisible to your customers until
it is not, and by then they have lost coupons. Count your own open
reservations rather than comparing reserve calls with cancel-reservation
calls: posting a transaction releases its reservation without any call
from you, so the two would never match.
Where things break
Section titled “Where things break”| Symptom | Likely cause |
|---|---|
Every call 403 | Store id is not the one from GET /stores, or case was mangled |
| Every customer looks new | Empty-array miss treated as an error |
| Coupons disappear over time | Reservations from abandoned carts never released |
| Address, departments or segments blanked after an edit | PUT left them out |
| Members stop receiving marketing after an edit | PUT left out receive_sms or receive_email |
| Members receiving marketing they never chose | Create left out receive_sms or receive_email |
| Merchant sees no online sales | origin.channel not set to "OnlineStore" |
| Points look wrong to customers | Showing remaining_points, not points |
| Orders at odd times | created_at sent without an offset |
| Duplicate transactions | external_id not deterministic, or origin changed between retries |
Support
Section titled “Support”- Status: diller.statuspage.io
- SMS delivery status: status.linkmobility.com (we send SMS through LINK Mobility; a delivery problem may be visible here first)
- Help centre: diller.frontkb.com
When raising an issue, include the store id, the external_id of the
affected order, the endpoint, the timestamp with timezone, and the full
response body. That turns a multi-day thread into one reply.
Related reading
Section titled “Related reading”Other Diller articles worth knowing about:
| Article | Why |
|---|---|
| API — getting started for POS | The in-store side; useful if the merchant runs both |
| Swagger overview | Generated endpoint index |
| Points2currency coupons | Points-as-money rewards |
| 3rd party integrations | WooCommerce, Shopify, Magento, Klaviyo, Mailchimp |
The machine-readable contract is in openapi/diller-api-v2.json.
