The data endpoints a connected partner calls with its access token.
Once a partner has completed the OAuth flow and exchanged its integration token, it holds an access token scoped to a single connected store. Every Partner Endpoint is authorised with that token.
Pass the access token as the access_token query parameter:
POST /v1/orders?access_token={accessToken}The access token identifies the connected store; you do not send client_id/client_secret on these data endpoints (those are only used in the OAuth flow and for token refresh).
POST /v1/auth/token (see Tokens & lifecycle).403.An access token grants the connected store the ability to:
| Capability | Endpoint |
|---|---|
| Update the store profile | PUT /v1/stores |
| Read store settings (e-receipts on/off) | GET /v1/stores |
| Get an upload URL for the customers list | GET /v1/customers |
| Send an order / transaction | POST /v1/orders |
| Read an order (for e-receipts) | GET /v1/orders |
Each is documented in the following sections. All endpoints are served under the /v1 base path.
currency code (e.g. "USD").
2026-06-28T14:03:00.000Z).application/json.Create or update the profile of the connected store — its name, address, contact details and currency. Keeping this current improves ad localisation and receipt accuracy.
PUT /v1/stores?access_token={accessToken}
Content-Type: application/json| Field | Type | Required | Description |
|---|---|---|---|
storeName | string | yes | Display name of the store. |
storeAddress | string | yes | Street address line. |
storeCountryCode | string | yes | ISO country code (e.g. US). |
storeCity | string | no | City. |
storeState | string | no | State / region. |
storePostalCode | string | no | Postal / ZIP code. |
storePhoneNumber | string | no | Public contact number. |
storeCurrency | string | no | ISO currency code (e.g. USD). Defaults to the store's configured currency. |
{
"storeName": "Bridge Street Bakery",
"storeAddress": "120 Bridge Street",
"storeCity": "Austin",
"storeState": "TX",
"storeCountryCode": "US",
"storePostalCode": "78701",
"storePhoneNumber": "+1-512-555-0142",
"storeCurrency": "USD"
}200{
"store": {
"id": "…",
"name": "Bridge Street Bakery",
"phoneNumber": "+1-512-555-0142",
"address": {
"addressLine": "120 Bridge Street",
"city": "Austin",
"state": "TX",
"country": "US",
"postalCode": "78701"
},
"currency": "USD"
}
}| Status | Meaning |
|---|---|
400 | A request field is missing or invalid. |
403 | access_token is missing, expired, or invalid. |
500 | Unexpected server error. |
See Errors for the shared error model.
Send the store's customer list so Rulrr can build targeted and look-alike audiences for campaigns. This is the foundation of initial targeting: the better the customer data, the stronger the audiences Rulrr can create on the ad networks.
Because customer lists can be large, the upload is a two-step, pre-signed URL process — you never post the list to the API directly.
GET /v1/customers?access_token={accessToken}Response 200
{ "uploadUrl": "https://…s3…/customers/…?X-Amz-Signature=…" }The uploadUrl is a short-lived, pre-signed URL that accepts a single file upload.
PUT the customer records as JSON to the uploadUrl returned above. Each record should contain whatever identifiers you have; email and phone are the most valuable for matching.
[
{
"firstName": "Dana",
"lastName": "Levy",
"email": "dana@example.com",
"phoneNumber": "+15125550101",
"city": "Austin",
"countryCode": "US"
},
{
"firstName": "Sam",
"lastName": "Cohen",
"email": "sam@example.com",
"phoneNumber": "+15125550102"
}
]Rulrr ingests the file, de-duplicates customers (by email, falling back to phone), and uses the result to seed audiences. Re-send the list periodically to keep audiences fresh; ingestion is idempotent, so re-uploading the same customers will not create duplicates.
| Field | Recommended | Notes |
|---|---|---|
email | strongly | Primary match key. |
phoneNumber | strongly | Fallback match key; E.164 format preferred. |
firstName, lastName | yes | Improves match quality and personalisation. |
city, countryCode | optional | Helps geo-targeting. |
| Status | Meaning |
|---|---|
403 | access_token is missing, expired, or invalid. |
400 | Invalid request. |
500 | Unexpected server error. |
Privacy. Only send customer data you are permitted to share for advertising. Rulrr uses it to create and measure audiences on the merchant's behalf.
Send each completed order (transaction) so Rulrr can measure conversions and attribute revenue to campaigns. This is how the merchant sees real sales impact — and how Rulrr distinguishes new vs. returning customers.
POST /v1/orders?access_token={accessToken}
Content-Type: application/json| Field | Type | Required | Description |
|---|---|---|---|
orderId | string | yes | Your unique ID for the order. Re-sending the same orderId updates the existing order. |
orderPrice | string | yes | Total in the currency's minor unit (e.g. cents). |
orderCurrency | string | yes | ISO currency code (e.g. USD). |
createdAt | string | yes | ISO-8601 timestamp of the order. |
updatedAt | string | no | ISO-8601 timestamp of the last change. |
customerFirstName | string | no | Customer first name. |
customerLastName | string | no | Customer last name. |
customerPhoneNumber | string | no | Customer phone (enables SMS e-receipts). |
customerEmail | string | no | Customer email. |
orderDetails | object | no | Pass-through detail: status, type, line items, payments (see below). |
store | object | no | Store snapshot (same fields as Update Store Profile); lets you create/update the store inline. |
{
"orderId": "POS-10293",
"orderPrice": "4200",
"orderCurrency": "USD",
"createdAt": "2026-06-28T14:03:00.000Z",
"customerFirstName": "Dana",
"customerLastName": "Levy",
"customerPhoneNumber": "+15125550101",
"customerEmail": "dana@example.com",
"orderDetails": {
"orderStatus": "CLOSED",
"orderType": "dine-in",
"orderItems": [
{ "itemId": "SKU-1", "itemName": "Sourdough", "itemPrice": "1200", "itemQuantity": 2, "itemTax": "0" }
],
"orderPayments": [
{ "paymentType": "card", "paymentId": "pay_1", "paymentSum": "4200", "paymentCardType": "visa", "paymentLast4": "4242" }
]
}
}record), so the order is tied to a person.
organic, or anonymous — this powers conversion stats and revenue attribution.
CLOSEDwith a customer phone number (see E-receipts).
200{ "statusCode": 200 }| Status | Meaning |
|---|---|
400 | A required field is missing or invalid. |
403 | access_token is missing, expired, or invalid. |
500 | Unexpected server error. |
Send orders continuously. Streaming every closed transaction (not just a daily batch) gives the most accurate, near-real-time conversion measurement.
Some integrations offer e-receipts — an SMS receipt sent to the customer at checkout. E-receipts both delight customers and strengthen Rulrr's customer/consent data. This section covers reading the store's settings and the e-receipt read endpoint.
Check whether e-receipts are enabled for the connected store.
GET /v1/stores?access_token={accessToken}Response 200
{ "greenInvoices": true }greenInvoices reflects the e-receipt preference the merchant chose on the Rulrr-Connect screen. When true, the integration should offer the e-receipt step at the point of sale.
E-receipts are triggered automatically by Rulrr when all of the following hold for an order sent via POST /v1/orders:
greenInvoices: true), andorderDetails.orderStatus is CLOSED, andWhen triggered, Rulrr sends the customer an SMS linking to a hosted receipt at https://connect.rulrr.com/inv/{orderId}.
If your terminal supports it, prompt the cashier for the customer's phone number at checkout so the e-receipt can be sent. If the customer opts in and enters a valid number, you can dismiss the printed receipt in favour of the SMS one.
The hosted receipt page reads the order via:
GET /v1/orders?orderId={orderId}This returns the order with its line items, payments and store snapshot for display. It is gated: the store must have e-receipts enabled, the order must be CLOSED, and the order must have an associated customer with a phone number — otherwise it returns 403/404.
Most partners never call GET /v1/orders directly; it backs the hosted e-receipt page. It is documented here for completeness.Integration Endpoints use standard HTTP status codes. A non-2xx response indicates the request was not applied.
| Status | Meaning | Typical cause |
|---|---|---|
200 | Success | The request was accepted and applied. |
400 | Bad request | A required field or parameter is missing or malformed. |
403 | Forbidden | access_token is missing, expired, revoked, or invalid — or the resource is not enabled for this store (e.g. e-receipts off). |
404 | Not found | The referenced resource (e.g. an order) does not exist or is not visible. |
410 | Gone | A one-time resource was already consumed — e.g. integration tokens can only be exchanged once. |
500 | Server error | Unexpected error on Rulrr's side; safe to retry with backoff. |
400 — fix the request; do not retry unchanged. Validate required fields and money/timestampformats (minor units as strings; ISO-8601 timestamps).
403 — refresh your access token (see Tokens & lifecycle); if it still fails,the integration may have been revoked — re-run the OAuth flow.
404 / 410 — the resource is missing or already used; do not retry blindly.500 — retry with exponential backoff. If it persists, contactorderId — re-sending the same orderId updates the existing orderrather than creating a duplicate, so retries are safe.