myne Connect Brands API (1.0.0)

Download OpenAPI specification:

License: Proprietary

Brand-scoped API for partners building CRM, sync, and loyalty integrations.

Use this reference when you need to keep myne in sync with your own systems—CRM, website, middleware, or POS extensions—without waiting for a packaged connector.

Create credentials in myne at API Credentials (brand admins).

Then pick how you will call Connect: HTTP Basic (this brand, no token) or OAuth (Bearer token for this brand, or another brand that Allows the client).

Brand hierarchy: Every resource path is scoped to one Brand. Some brands sit in a Head office Organisation (Head office group). Discover that on Get credential scope and brand identity (GET /v1/me) or Get brand bootstrap configuration (GET …/brand): read response.brand.organisation (or the brand object in the Brand response). It names role, head_office_brand, and sibling_brands. Solo brands return organisation: null. Paths do not become org-wide—use those ids only as context (for example Collect Across Venues stamp labels).

Terms in bold, or linked to the glossary, are defined at the bottom of this page (for example Surface, External source, API Credentials).

Base URL: https://connect.myne.network (production) or https://connect.dev.myne.network (development).

Authentication: HTTP Basic or Bearer (POST /v1/token).

Create a Client ID and secret in myne at API Credentials while signed in as a brand admin. The Client Secret is shown once when you create or rotate.

Send Authorization: Basic … or Authorization: Bearer … on resource calls to connect.myne.network /v1. The HTTP Basic and OAuth sections walk through each method.

Do not rely on HTTP clients following redirects for authenticated calls — many strip Authorization on cross-origin redirects. Connect v1 routes respond in place (no auth redirect).

Response shape: Successful resource calls return JSON with message (status text) and response (payload). Resource errors return { "message": "…" } with an appropriate HTTP status. POST /v1/token success is { access_token, token_type, expires_in, brand_id } (plus refresh_token for authorization-code); token errors are { error, error_description }. Field naming: All request and response JSON fields, and query parameters, use snake_case (for example brand_id, amount_in_cents, has_more).

Helpful downloads

Ready-made files for tooling and import:

Import the collection and environment into Postman (or use Import → Link with these URLs). Set client_id and client_secret from API Credentials. Run Get credential scope (Basic GET /v1/me) or Get an access token (this brand) then Get credential scope with Bearer. For other brands, authorize in the browser, then Get an access token (authorization code) and Refresh an access token. Authorize cannot run inside Postman.

Glossary

Expand a term for its definition. How-to for a call lives on that operation (and its section)—not here.

Brand

The business using myne—your organisation in the product, and the tenant for every Connect route.

Call GET /v1/me first to learn your brand_id, then pass it in the path on other routes. API Credentials for the creating brand are scoped to that brand only. Other brands must Allow the same Client ID at /oauth/authorize.

GET /v1/me and GET …/brand return partner-safe brand fields. When the brand is in a Head office group, see Organisation (Head office group) on brand.organisation. Paths stay scoped to the authenticated brand — org fields are context only.

Organisation (Head office group)

A Head office group of brands: one Head office brand and one or more venue brands that share customers and can run cross-venue offers.

Where to see it: After auth, call GET /v1/me (read response.brand.organisation) or GET /v1/brands/{brand_id}/brand (same object on the brand in the response array). Solo brands return organisation: null.

Fields: - id / name — the organisation - role — venue or head_office for the brand you authenticated as - head_office_brand — parent Head office (id + name; same as this brand when role is head_office) - sibling_brands — peer venue brands (id + name; excludes this brand and the Head office)

Resource paths do not become organisation-scoped. Use these ids to understand relationships (for example Collect Across Venues stamp labels on evaluate venue_progress). Head office Collect Across Venues that target a child brand can appear on that child’s promotion catalog and redeem path for that type only.

Location

A specific venue or site customers visit—how you split offers, links, and reporting by place.

Use location_id to scope customer browse, sync payloads, and promotion lists to one venue.

Customer

Someone you recognise with a full profile—usually a name and contact details you can message or segment.

Customer IDs come from browse, sync, create/upsert, or your POS. Most loyalty and promotion calls need a customer id (or an external id you can resolve).

GET customer (by id or by external id) returns linked system ids in extended[], not a single top-level source/external_id. The profile includes pass id, Brand Points, and myne cashback. Visit totals sit on stats.

Visitor

Spend or activity you can see before you have a full profile—or alongside one—when someone has not fully signed up.

Customer browse returns visitors only when you set include_visitors=true. Otherwise results are known customers.

Business

A B2B account (company or organisation) linked to contacts in myne.

This is not the same as a location. A business may span multiple venues; a location is one physical site.

Connection state

How well you know someone on a profile:

  • connected — they have joined your programme through a join experience
  • known — you can identify them, but they may not have fully connected
  • unknown — you see activity without full identity

Filter customer browse with the connection query parameter. This is about relationship state on the profile—not plan usage metering named “connections”.

Customer group

A named audience of customers in myne. Paths use filter-groups; the partner-facing name is always customer group.

Membership can be maintained by dynamic refresh, scheduled refresh, import replace, or automation-driven changes.

Live offers also have a Claimed - {offer name} group. Treat it as a read segment: membership is added when a customer claims the offer on the join page. Connect can list the group and its members; it cannot add members or assign a claim.

Connect lists which customer groups exist, which customers are in one group, and which customer groups a single customer belongs to. Scope browse or search with customer_group_id.

Business group

A named audience of businesses (B2B accounts) in myne—the account-side counterpart to a Customer group.

Membership can use the same patterns as customer groups. Business groups are configured in the product; Connect Brands does not currently expose dedicated business-group list routes.

Frequency

How often someone tends to visit—New, Frequent, or Infrequent.

Returned on customer rows and available as a browse filter so you can tailor welcome paths vs loyalty depth.

Engagement

A simple read on whether someone is active with your brand or drifting—useful for quick prioritisation on a profile.

Returned on customer profiles when myne has enough signal to classify them.

Extended profile

Timeline beyond the core customer or business fields: POS records, marketing activities, transactions, custom properties, and similar.

On GET customer, extended[] is the identity list (source + external_id per connected system). The /customers/{id}/extended route is the activity timeline, not that identity list.

Credit

Stored value on a partner loyalty programme (for example Wrapped/Giftit or myne Cashback).

Credit endpoints read balance, ledger history, and add value. A customer may have no linked credit yet—in that case balance reads as zero and there is nothing to top up until credit is linked.

GET customer cashback is the internal cashback ledger for the brand, not a live Wrapped or Giftit credit GET. Use the credit endpoints when you need that partner programme's current balance.

Points

Brand Points balance and earn/redeem history when Brand Points is enabled for the brand.

Points endpoints mirror credit: balance, ledger, and top-up. Top-ups always need a reason for the staff ledger.

Wallet pass

Apple Wallet or Google Wallet identifiers tied to a customer's credit or rewards pass.

GET customer returns pass_id (the loyalty pass code) with points and cashback. Wallet serials are also returned alongside balance on the credit endpoint.

Sync batch

The main write path for pushing contacts, businesses, links, and extended metadata into myne.

Send up to 50 typed items per request. Prefer sync for bulk imports; use single customer upsert for one-off registrations. See external_id and external_data.

external_id and external_data

external_id is your identifier for a record (for example a CRM id or website user id). external_data is any extra attributes you choose to store on the core row.

Lookups and promotion evaluate/apply resolve that same external_id under your External source. GET customer lists every known source and id in extended[] rather than a single top-level pair. For extra partner metadata, also write extended rows under your source.

External source

The integration key (source) that owns a customer or business external_id and extended fields.

Each API Credentials client has one source, derived from the app label in Integrations. GET …/me returns it as source.

Do not invent a source, and do not send source on write requests. Writes always stamp your credential’s source. Lookups default to your source.

CRM embed

An embedded myne CRM panel inside your own app.

Mint a short-lived Bearer token from Connect, then load the widget for a specific customer or business.

API Credentials

Client ID and Client Secret for partner server-to-server access (formerly Custom API Basic).

Create them in myne at API Credentials while signed in as a brand admin. Copy the Client Secret when it is shown—it cannot be retrieved later.

Two uses, one Client ID: HTTP Basic or POST /v1/token with grant_type=client_credentials only reaches the creating brand. Other myne brands Allow the same Client ID in the browser (https://app.myne.network/oauth/authorize); that returns a code you exchange for tokens for that brand.

Resource calls accept Authorization: Basic … or Authorization: Bearer …. Access tokens last one hour; issuing another token does not cut earlier ones short. Authorization-code installs also return a refresh token. A brand can have more than one live refresh token for the same Client ID (for example two partner entities). Refreshing one does not invalidate the others. Revoke or rotate the secret stops them all.

Outbound webhook

An HTTPS destination myne POSTs when a subscribed brand event happens.

Create subscriptions with Connect (/v1/brands/{brand_id}/webhooks) or in Settings → Webhooks → Outgoing. The signing secret is returned only on create and rotate. Partners only see destinations their Custom API app created. Poll collection GETs with updated_since when you prefer pull over push.

Topics include customer create/update, transactions, group membership, venue check-in, connection-form submit, and promotion redeem. The customer.created and customer.updated payloads include connection_type — connected when the customer has joined loyalty, known when myne has the customer but they have not joined, and unknown for an anonymous website visitor. It matches the connection_type on the customer list and get-customer endpoints.

Signature

HMAC-SHA256 of {unix_timestamp}.{rawBody} sent as X-Myne-Signature: t=<unix>,v1=<hex>.

Also send X-Myne-Topic and X-Myne-Delivery-Id. Verify with crypto.timingSafeEqual. Treat delivery_id as an idempotency key so retries are safe.

updated_since

Optional ISO-8601 timestamp on collection list and search routes. When set, only rows whose watermark is on or after that instant (UTC, inclusive) are returned. Omit the parameter for today's full list.

Most collections use updated_at. Credit and points ledgers use created_at. Invalid timestamps return 400.

Promotion

An offer set up in myne. It states what the customer gets, when it can be used, and where it can appear.

Each promotion can also say whether more than one offer may sit on the same order. Connect list, get, search, and evaluate responses include image_url (the offer image, or null).

Collect Across Venues (venue_unlock) is a passport offer: the same action at each selected site or Head office child brand unlocks a reward. On register/ordering evaluate (lsk/lso), progress is in venue_progress; incomplete passports use VENUE_UNLOCK_NOT_ELIGIBLE. Head office offers of this type that target a child brand are visible on that child’s Connect catalog and redeem path (this type only).

Some offers use Buy X Get Y rules. Evaluate promotions applies those on the open order.

Buy X Get Y

A promotion mechanic: the customer must buy quantity X of matching items, then quantity Y of matching items is discounted (often free).

When buy (X) and get (Y) use the same products or categories, the paid X units are reserved first. Y does not cancel X. Example: Buy 1 Get 1 Free needs two matching units — pay for the first, discount the second. Buy 3 Get 1 Free needs four matching units.

When buy and get are different products or categories, the customer still needs enough X on the order, and the discount applies only to matching Y lines.

If allow-repeat is on, each complete set of paid X plus discounted Y can apply again on the same order. Rolling Buy X Get Y can bank the buy side from earlier purchases in the period; then the current order only needs matching Y.

Surface

Where the sale happens. Examples: a join page, an ordering app, a register, or an online store.

Send surface to match that place: lsk for register, lso for ordering. Use the same value on evaluate, apply, and complete. Those open-order calls always need surface — do not send integration_type there.

On browse, customer list, and search you may send integration_type instead as a coarse list filter when you only need which promotions can show (ordering, listing, or ecommerce) from customer Show vs available groups, without knowing which app will evaluate the sale. Some availability values are marketing only and are not used on evaluate, apply, or complete.

Show vs available

Two audience rules on a promotion:

  • Show — who may see the offer
  • Available — who may use the offer

A customer can see an offer and still be unable to use it until they meet the available rules.

A separate redeem rule is join-page claim. When an offer requires it, evaluate returns non_redeemable_cause.code CLAIM_REQUIRED until the customer has claimed on the join page. That is not assigned by this API.

Order line pos_id

The product id for a line on the open order (cart.items[].metadata.pos_id). It comes from the catalogue at the place you are selling. Example: the register item id at a POS.

We need this on each line so we can match the order to the promotion rules. It is not your Custom API customer or product id.

Promotion stacking

Whether more than one promotion can sit on the same open order at once.

Each promotion has its own allow-stacking setting in myne. If stacking is allowed, lock each reward with the same order id. One complete call then records all of them.

basket_id and MYNE reference

Your id for the open order. Use a POS order id, or generate a unique id. In the API this field is named basket_id.

We need the same id on evaluate, apply, and complete so we treat them as one order. If paid sales already go to myne, write that same id onto the order with the prefix MYNE so myne can match the payment. If you send Complete promotions after the customer pays, you do not write that mark.

Transaction

A paid purchase stored in myne after the customer has paid.

Before payment, the sale is an open order. Recording a promotion redemption does not create this purchase. The purchase is created when the POS or ordering system sends the sale.

Activity

A CRM timeline entry on a contact—manual notes and calls you log via Activities, plus other rows that appear in the staff activity feed.

This is distinct from Customer events (POST …/events), which are integration-sourced timeline posts stamped with your External source.

Task

A staff follow-up work item in myne—title, status, due date, assignees, and linked contacts or businesses.

Connect can list and search tasks. Creating tasks via Connect is not available yet.

Authorisation

Start here. Create API Credentials in myne, then confirm which brand they reach before you call other routes.

You have one Client ID. Use it two ways:

  • HTTP Basic — send the ID and secret on each request. Creating brand only. No token step.
  • OAuth — mint a Bearer token for this brand, or for another myne brand that Allows the client.

Call Get credential scope and brand identity first. You do not pass brand_id on that path — the credential or token selects the brand. Use the returned brand_id on every other /v1/brands/{brand_id}/… route.

On that same response, read brand.organisation when present to see Head office / venue relationships (role, head_office_brand, sibling_brands). Details: Brand and Organisation (Head office group).

Send Authorization on every request to the final connect.myne.network /v1 URL. Do not rely on following redirects for auth.

Rotate secret keeps the same Client ID and invalidates outstanding access tokens. Partners do not create Auth0 apps.

Get credential scope and brand identity

Confirm your API Credentials (HTTP Basic or Bearer from POST /v1/token) and discover brand_id, partner-safe brand display settings, External source, and—when this brand is in a Head office group—brand.organisation (role, Head office parent, sibling venues).

Call this first when wiring a new integration. You do not pass brand_id on this path — the credential or access token selects the brand (creating brand for Basic / client_credentials; granted brand for authorization-code tokens).

Read response.brand.organisation to understand multi-brand relationships. Paths on other routes stay scoped to response.brand_id — see Brand and Organisation (Head office group) in the glossary.

Send Authorization: Basic or Authorization: Bearer on every request to the connect.myne.network /v1 URL. Do not rely on following redirects for auth.

See glossary: Brand, Organisation (Head office group), API Credentials, External source.

Authorizations:
basicAuthbearerAuth

Responses

Response samples

Content type
application/json
{
  • "message": "Authenticated successfully",
  • "response": {
    }
}

HTTP Basic

Send your Client ID and secret on each request. There is no token step.

This only reaches the creating brand — the brand where you added the client in myne.

  1. Open API Credentials as a brand admin. Add a client. Copy Client ID (myne_api_…) and Client Secret (shown once).

  2. Call GET https://connect.myne.network/v1/me with:

    Authorization: Basic base64(client_id:client_secret)

  3. Read response.brand_id and response.source. Use that brand_id on every other path. If response.brand.organisation is present, note role, head_office_brand, and sibling_brands for multi-venue context.

Path brand_id must match the credential. Resource errors look like { "message": "…" }.

OAuth

Mint a Bearer token, then send Authorization: Bearer {access_token} on resource calls. Access tokens last one hour. Issuing another access token does not invalidate earlier ones; they stay valid until that expiry, or until you rotate the secret or Revoke the grant.

Call POST https://connect.myne.network/v1/token (this Connect host only). JSON body is preferred. You can also send client_id and client_secret as HTTP Basic on that call, or as application/x-www-form-urlencoded.

Token errors use error / error_description (not the resource { message } envelope).

This brand

Use this when you only need the creating brand. There is no refresh token.

{ "grant_type": "client_credentials", "client_id": "myne_api_…", "client_secret": "…" }

Then call Get credential scope and brand identity with Authorization: Bearer {access_token}.

Other myne brands

Use this when another brand Allows your Client ID. Each Allow and code exchange issues its own refresh token. Refreshing one token rotates only that token; other refresh tokens for the same brand stay valid.

  1. On the client in API Credentials, save https redirect URLs (one per line, exact match). http localhost is allowed on development only. An empty redirect list cannot authorize.

  2. Send a brand admin to authorize in the browser:

    https://app.myne.network/oauth/authorize?client_id=myne_api_…&redirect_uri=https://partner.example/oauth/callback&response_type=code&state=YOUR_STATE

    Development: https://app.dev.myne.network/oauth/authorize with the same query. They sign in, pick that brand, and Allow. Deny returns error=access_denied to your redirect. Unknown redirects are not sent to an unregistered host. PKCE S256 is accepted (code_challenge and code_challenge_method=S256).

  3. Exchange the code (same redirect_uri, exact match). A code cannot be reused.

    { "grant_type": "authorization_code", "client_id": "…", "client_secret": "…", "code": "…", "redirect_uri": "…" }
    

    The response includes access_token, refresh_token, expires_in, and the granted brand_id.

  4. Refresh before the hour is up. That refresh token rotates: use the new refresh_token; the one you just used fails. Other refresh tokens for the same brand stay valid. Earlier access tokens stay valid until they expire.

    { "grant_type": "refresh_token", "client_id": "…", "client_secret": "…", "refresh_token": "…" }
    

Then call GET /v1/me or /v1/brands/{brand_id}/… with Bearer. Path brand_id must match the token.

Get an access token

Exchange API Credentials for a Connect access token. This route is on the Connect host only (POST /v1/token). Do not send a gateway JWT.

JSON body is preferred. client_id and client_secret may also be sent as HTTP Basic on this call, or as application/x-www-form-urlencoded.

  • grant_type=client_credentials — creating brand only. No refresh token.
  • grant_type=authorization_code — requires code and redirect_uri (exact match). Returns refresh_token. Code cannot be reused. A second Allow for the same brand adds another refresh token; existing ones stay valid.
  • grant_type=refresh_token — requires refresh_token; issues a new access token and rotates only the refresh token you sent. Other refresh tokens for the same brand stay valid. Earlier access tokens stay valid until they expire.

Access tokens last 3600 seconds. Issuing another access token does not invalidate earlier ones. Use Authorization: Bearer {access_token} on resource routes. brand_id in the token body is the creating brand (client credentials) or the granted brand (authorization code / refresh).

Authorize (browser, staff admin login): https://app.myne.network/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type=code&state={state}. PKCE S256 is accepted when code_challenge was sent on authorize.

See the OAuth section for the this-brand and other-brand walkthroughs.

Request Body schema: application/json
required
grant_type
required
string
Enum: "client_credentials" "authorization_code" "refresh_token"
client_id
required
string
client_secret
required
string
code
string
redirect_uri
string
refresh_token
string
code_verifier
string

Responses

Request samples

Content type
application/json
Example
{
  • "grant_type": "client_credentials",
  • "client_id": "myne_api_abc",
  • "client_secret": "your-client-secret"
}

Response samples

Content type
application/json
Example
{
  • "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
  • "token_type": "Bearer",
  • "expires_in": 3600,
  • "brand_id": 42
}

Brand

Partner-safe brand display settings—name, logos, colours, and contact fields.

Where to see relationships

  1. Call Get credential scope and brand identity (GET /v1/me) after auth — read response.brand.
  2. Or call Get brand bootstrap configuration (GET /v1/brands/{brand_id}/brand) for the same brand object without credential metadata.

When this brand is in a Head office group, organisation is present:

  • role — venue or head_office
  • head_office_brand — parent Head office (id + name)
  • sibling_brands — peer venue brands (id + name; excludes this brand and the Head office)

Solo brands return organisation: null. Resource paths stay scoped to this brand’s id — org fields are context only (see Organisation (Head office group)). For Collect Across Venues on evaluate, stamp brand ids on venue_progress match these ids.

Get brand bootstrap configuration

Load partner-safe brand settings—display name, logos, colours, headings, contact fields, and organisation hierarchy when present.

This is the same brand object as response.brand on GET …/me. Use when you need brand config without credential metadata.

When the brand is in a Head office group, inspect organisation.role, organisation.head_office_brand, and organisation.sibling_brands. Solo brands return organisation: null. Paths stay brand-scoped.

Returns one brand object in response as a single-item array. Returns 404 when the brand is not found.

See glossary: Brand, Organisation (Head office group).

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "Brands fetched successfully",
  • "response": []
}

Integrations

Connected apps and data sources for the brand, without secrets or tokens.

List connected integrations for a brand

Return every app connected to the brand—the same integrations staff see in myne Settings.

Each row includes id, access_name, app_name, label, source, category, and whether it matches your API credentials (is_self).

Secrets, OAuth tokens, and raw integration payloads are never included.

See glossary: External source, API Credentials.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "Integrations fetched successfully",
  • "response": [
    ]
}

Location

Venues for the brand. Use location IDs when scoping customers, sync, and promotions.

List locations for a brand

Return every venue for the brand—the same rows staff see in myne.

Use location IDs in customer browse filters, sync payloads, and promotion scoping.

See glossary: Location, Brand.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
query Parameters
updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with updated_at on or after this instant are returned (compared in UTC, inclusive). Omit for the full list. Invalid values return 400.

Responses

Response samples

Content type
application/json
{
  • "message": "Locations fetched successfully",
  • "response": [
    ]
}

Get a location by id

Load one venue by location_id for the brand.

Returns partner-safe fields such as name, phone, address, uuid, valid, and new_check_in_enabled.

Use after listing locations or when resolving a venue from sync payloads. Returns 404 when the ID is not in this brand.

See glossary: Location.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
location_id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "Location fetched successfully",
  • "response": {
    }
}

Customer

Browse, create or update, and load customer profiles—including extended timeline data.

Get a customer by external id

Resolve a myne customer from your CRM or PMS external_id without scanning browse results.

When source is omitted, lookup uses your Custom API app name (the label shown in Integrations)—the same source stamped when you synced or upserted the contact. Pass source explicitly only when you need IDs synced under another integration.

Returns the customer with connected-system identities (extended[]), pass id, Brand Points, myne cashback, lifetime stats, and loyalty join status (connection_type — connected when the customer has joined loyalty, known when not, unknown for an anonymous website visitor), or 404 when no match exists for this brand. connection_type matches the customer list and the get-customer-by-id endpoint. Identities are not a single top-level source/external_id. Cashback here is the internal cashback ledger, not a live Wrapped or Giftit credit GET.

Evaluate/apply use this same external_id path when you omit customer_id, but they do not load identities or loyalty.

See glossary: Customer, external_id and external_data, External source, Credit, Points.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
query Parameters
external_id
required
string

Your integration's identifier for the customer.

source
string

Origin system for the external_id. When omitted, defaults to your Custom API app name (Integrations label). Read-only filter for cross-integration lookups.

Responses

Response samples

Content type
application/json
{
  • "message": "Customer fetched successfully",
  • "response": {
    }
}

Upsert extended customer data by external id

Merge JSON extended fields for a customer identified by external_id.

Use this when you want partner metadata or alternate source ids stored under your Custom API app without relying only on top-level email/phone/name. Data is stored under your app source only—do not send source in the body.

If no customer exists for that external_id yet, one is created. You may optionally pass email, phone, first_name, and last_name on create.

See glossary: Customer, Extended profile, External source, external_id and external_data.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
Request Body schema: application/json
required
external_id
required
string

Your integration's identifier for the customer.

required
object

JSON fields to merge into customer_extended for your API app source.

email
string <email>

Optional. Used when creating the customer if they do not exist yet.

phone
string
first_name
string
last_name
string

Responses

Request samples

Content type
application/json
{
  • "external_id": "string",
  • "data": { },
  • "email": "user@example.com",
  • "phone": "string",
  • "first_name": "string",
  • "last_name": "string"
}

Response samples

Content type
application/json
{
  • "message": "Customer extended data upserted successfully",
  • "response": {
    }
}

List declared contact-extended properties for your source

Return the top-level contact-extended fields your app has declared for this brand under your External source.

This is the partner-declared catalog only (not staff-added extras). Values still live in customer_extended.data via extended upsert; declaring properties does not validate or strip undeclared keys on write.

See glossary: Customer, Extended profile, External source.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer

Brand id from your credential scope.

Responses

Response samples

Content type
application/json
{
  • "message": "Customer extended properties fetched successfully",
  • "response": {
    }
}

Replace declared contact-extended properties for your source

Full-replace the top-level contact-extended fields your app stands behind for this brand.

Send properties as an array of { key, type, label?, description? } (max 50). Types: string, number, boolean, link, date. Keys must match ^[a-z][a-z0-9_]*$ (max 64) and the top-level JSON keys you write on extended upsert. Empty properties: [] clears your partner-declared catalog for this source.

Source is always your Custom API app—do not send source. This does not change how extended upsert merges JSON.

See glossary: Customer, Extended profile, External source.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer

Brand id from your credential scope.

Request Body schema: application/json
required
required
Array of objects <= 50 items

Full replace list for this brand + your External source. Empty array clears your partner-declared catalog.

Responses

Request samples

Content type
application/json
{
  • "properties": [
    ]
}

Response samples

Content type
application/json
{
  • "message": "Customer extended properties replaced successfully",
  • "response": {
    }
}

Upsert a customer by external id

Create or update a customer from your website, CRM, or PMS using external_id.

Send top-level profile fields when you have them (email, phone, name). Source is always your Custom API app—do not send source.

Send connection_type: "connected" when the person is already a loyalty member in your app — myne marks them as joined (requires an email or phone on the request, or one already stored for the customer). Omitting it, or sending known / unknown, never changes their connection status.

That external_id is what you use later for promotion evaluate/apply and by-external-id lookups under your External source. For additional partner ids or opaque metadata, also write extended data (POST …/customers/by-external-id/extended or sync contact_extended).

Prefer this for single registrations; use Sync batch for bulk imports.

See glossary: Customer, external_id and external_data, Sync batch.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
Request Body schema: application/json
required
external_id
required
string

Your website or CRM identifier for the customer.

email
string <email>
phone
string
first_name
string
last_name
string
marketing_opt_in_email
boolean

Marketing email opt-in stored on the customer profile.

connection_type
string
Enum: "connected" "known" "unknown"

Optional loyalty connection status. connected marks the customer as joined to loyalty (requires an email or phone — sent on this request or already stored for the customer). known and unknown never change connection status, and unrecognised values are ignored.

object

Optional opaque attributes stored on the customer.

Responses

Request samples

Content type
application/json
{
  • "external_id": "string",
  • "email": "user@example.com",
  • "phone": "string",
  • "first_name": "string",
  • "last_name": "string",
  • "marketing_opt_in_email": true,
  • "connection_type": "connected",
  • "traits": { }
}

Response samples

Content type
application/json
{
  • "message": "Customer upserted successfully",
  • "response": {
    }
}

Browse customers for a brand

Search and page through customers for a brand. Use cursor from response.next_cursor for the next page.

Filter by location, Connection state, or Frequency. Set include_visitors=true to include unidentified Visitor records.

Pass updated_since (ISO-8601, compared in UTC) to poll only customers changed on or after that timestamp.

Typical first step before loading a single profile or extended timeline.

See glossary: Customer, Visitor, Connection state, Frequency, Engagement.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer

ID of the brand (tenant) to browse customers for.

query Parameters
limit
integer [ 1 .. 100 ]
Default: 15

Page size. Clamped to 1–100.

cursor
string

Opaque pagination cursor returned as response.next_cursor from the previous page. Omit for the first page.

query
string

Free-text search across name, email, phone, and wallet/credit identifiers.

include_visitors
boolean
Default: false

Accepts true, 1, or yes. When truthy, include unidentified visitor records; otherwise only known customers are returned (default).

sort_by
string
Default: "total_spent"
Enum: "last_seen" "transaction_count" "total_spent" "tenure" "frequency" "engagement"

Sort key for ranking customers.

sort_direction
string
Default: "asc"
Enum: "asc" "desc"

Sort direction.

locations
string

Comma-separated business/location IDs to restrict the browse to (e.g. 12,34).

connection
string
Enum: "connected" "known" "unknown"

Filter by connection state.

frequency
string
Enum: "frequent" "infrequent" "new"

Filter by brand frequency bucket.

engagement
string

Filter by engagement classification when available.

customer_group_id
integer

Restrict browse to members of one customer group.

search_fields
string

Comma-separated search field keys to limit free-text query matching.

updated_since
string <date-time>

ISO-8601 timestamp. When set, only customers with updated_at on or after this instant are returned (compared in UTC).

Responses

Response samples

Content type
application/json
{
  • "message": "Customer records fetched successfully (known only)",
  • "response": {
    }
}

Record a customer event

Append an event to the customer timeline (for example a form submission or in-app action).

Requires event_name. Optional: event_data, event_time, location_id, and external_id for idempotency.

Events are stamped with your External source from credentials. This is not the same as recording a CRM Activity (notes and calls).

See glossary: Activity, External source.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
customer_id
required
integer
Request Body schema: application/json
required
event_name
required
string

Event label on the customer timeline (e.g. form_submitted).

event_time
string <date-time>

When the event occurred (defaults to now).

object

Arbitrary JSON payload for the event.

event_value
number
location_id
integer
external_id
string

Optional partner event id for correlation.

is_visible_to_customer
boolean
Default: false

Responses

Request samples

Content type
application/json
{
  • "event_name": "string",
  • "event_time": "2019-08-24T14:15:22Z",
  • "event_data": { },
  • "event_value": 0,
  • "location_id": 0,
  • "external_id": "string",
  • "is_visible_to_customer": false
}

Response samples

Content type
application/json
{
  • "message": "Customer event recorded successfully",
  • "response": {
    }
}

Record a customer event by external id

Same as recording a customer event, but resolve the person with your website external_id instead of customer_id.

Pass external_id (contact) plus event_name. Use event_external_id for the event’s own id.

Lookup uses your credential External source.

See glossary: external_id and external_data, External source, Activity.

Authorizations:
basicAuthbearerAuth
query Parameters
external_id
string

Contact external_id. Prefer the body field; query is accepted for convenience.

Request Body schema: application/json
required
external_id
required
string

Your website or CRM identifier for the customer.

event_name
required
string

Event label on the customer timeline (e.g. form_submitted).

event_time
string <date-time>
object
event_value
number
location_id
integer
event_external_id
string

Optional partner id for this event (not the contact external_id).

is_visible_to_customer
boolean
Default: false

Responses

Request samples

Content type
application/json
{
  • "external_id": "string",
  • "event_name": "string",
  • "event_time": "2019-08-24T14:15:22Z",
  • "event_data": { },
  • "event_value": 0,
  • "location_id": 0,
  • "event_external_id": "string",
  • "is_visible_to_customer": false
}

Response samples

Content type
application/json
{
  • "message": "Customer event recorded successfully",
  • "response": {
    }
}

Search customers with advanced filters

Search and page through customers using a JSON body with the same filters as GET …/customers (cursor, limit, query, locations, sort_by, sort_direction, connection, frequency, engagement, customer_group_id, search_fields, updated_since, include_visitors).

Prefer GET …/customers for simple query-string browse; use this when filters are easier to express in JSON.

See glossary: Customer, Visitor, Connection state.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
Request Body schema: application/json
required
cursor
string
limit
integer [ 1 .. 100 ]
Default: 15
query
string
include_visitors
boolean
Default: false
sort_by
string
Default: "total_spent"
Enum: "last_seen" "transaction_count" "total_spent" "tenure" "frequency" "engagement"
sort_direction
string
Default: "asc"
Enum: "asc" "desc"
Array of integers or string
connection
string
Enum: "connected" "known" "unknown"
frequency
string
Enum: "frequent" "infrequent" "new"
engagement
string
customer_group_id
integer
search_fields
Array of strings
updated_since
string <date-time>

Responses

Request samples

Content type
application/json
{
  • "cursor": "string",
  • "limit": 15,
  • "query": "string",
  • "include_visitors": false,
  • "sort_by": "last_seen",
  • "sort_direction": "asc",
  • "locations": [
    ],
  • "connection": "connected",
  • "frequency": "frequent",
  • "engagement": "string",
  • "customer_group_id": 0,
  • "search_fields": [
    ],
  • "updated_since": "2019-08-24T14:15:22Z"
}

Response samples

Content type
application/json
{
  • "message": "Customer records fetched successfully (known only)",
  • "response": {
    }
}

Get a customer by id

Load one customer profile with connected-system identities (extended[]), pass id, Brand Points, myne cashback, lifetime transaction stats, and loyalty join status (connection_type).

connection_type is connected when the customer has joined loyalty, known when myne has the customer but they have not joined, and unknown for an anonymous website visitor. It matches the connection_type on the customer list.

Identities are listed in extended[], not as a single top-level source/external_id. Cashback is the internal cashback ledger, not a live Wrapped or Giftit credit GET. Visit totals sit on stats.

Use the customer_id from browse, sync batch, or your POS. Returns 404 when the ID is not in this brand.

See glossary: Customer, External source, Credit, Points.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
customer_id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "Customer fetched successfully",
  • "response": {
    }
}

Get extended customer profile

Fetch a customer's timeline: external POS records, marketing activities, and transactions.

Paginate with limit and offset. Set payments=true to include payment line items on each transaction.

Use when you need history beyond the summary fields on the main customer endpoint.

See glossary: Extended profile, Customer.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
customer_id
required
integer
query Parameters
limit
integer [ 1 .. 100 ]
Default: 25

Maximum timeline records to return per collection (activities, transactions).

offset
integer [ 0 .. 10000 ]
Default: 0

Zero-based offset into the timeline.

payments
boolean

When true, include payment detail objects inside each transaction record. Defaults to false.

Responses

Response samples

Content type
application/json
{
  • "message": "Customer extended data fetched successfully",
  • "response": {
    }
}

Customer groups

Customer groups and which customers belong to them. Membership may refresh dynamically, on a schedule, via import replace, or through automation-driven changes.

List customer groups

Return every active customer group for the brand (id and name), including Claimed - … groups for live offers.

Use customer group IDs when exporting membership or scoping customer browse (customer_group_id). Deleted customer groups are omitted. Membership may be maintained by dynamic refresh, scheduled refresh, import replace, or automation-driven changes—see glossary. Claimed-group membership is join-page claim, not an API write.

See glossary: Customer group.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
query Parameters
updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with updated_at on or after this instant are returned (compared in UTC, inclusive). Omit for the full list. Invalid values return 400.

Responses

Response samples

Content type
application/json
{
  • "message": "Filter groups fetched successfully",
  • "response": [
    ]
}

Browse customers in a customer group

Page through known customers who belong to one customer group, including Claimed - … groups (read-only membership from join-page claim).

Uses the same cursor and limit pagination as customer browse. Pass sort_by and sort_direction for ranking within the customer group.

See glossary: Customer group, Customer.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
group_id
required
integer
query Parameters
limit
integer [ 1 .. 100 ]
Default: 15
cursor
string

Pagination cursor from response.next_cursor.

sort_by
string
Default: "total_spent"
Enum: "last_seen" "transaction_count" "total_spent" "tenure" "frequency" "engagement"
sort_direction
string
Default: "asc"
Enum: "asc" "desc"
updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with updated_at on or after this instant are returned (compared in UTC, inclusive). Omit for the full list. Invalid values return 400.

Responses

Response samples

Content type
application/json
{
  • "message": "Customer records fetched successfully (known only)",
  • "response": {
    }
}

List customer groups for a customer

Return the customer groups a customer currently belongs to.

Useful for checking offer eligibility, personalising messaging, or syncing customer-group membership to an external CRM.

See glossary: Customer group, Show vs available.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
customer_id
required
integer
query Parameters
updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with updated_at on or after this instant are returned (compared in UTC, inclusive). Omit for the full list. Invalid values return 400.

Responses

Response samples

Content type
application/json
{
  • "message": "Successfully fetched customer filter groups",
  • "response": [
    ]
}

Credit

Stored-value / cashback balance, ledger history with reason, and top-up.

Get customer credit balance and wallet pass identifiers

Look up a customer's credit balance and Wallet pass identifiers (Apple Wallet and Google Wallet).

Balance is fetched live from the loyalty partner when credit is linked. Otherwise giftcard_code is null and balance is 0.

See glossary: Credit, Wallet pass.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
customer_id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "ok",
  • "response": {
    }
}

Add credit to a customer

Add stored value to a customer's linked credit.

Send amount and reason in the body. Reason is stored for audit and appears in the credit ledger. note is accepted as a legacy alias for reason for one release.

Supply idempotency_key when retrying so duplicate credits are not applied. The customer must already have linked credit.

See glossary: Credit.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
customer_id
required
integer
Request Body schema: application/json
required
amount
required
number

Dollar amount of credit to add.

reason
required
string

Required reason for the credit transaction (shown in the staff ledger).

note
string

Deprecated alias for reason. Prefer reason.

idempotency_key
string

Optional client-supplied key for safe retries.

Responses

Request samples

Content type
application/json
{
  • "amount": 10,
  • "reason": "Birthday bonus",
  • "idempotency_key": "credit-topup-001"
}

Response samples

Content type
application/json
{
  • "message": "ok",
  • "response": {
    }
}

Get customer credit ledger

List credit ledger entries for a customer, newest first: amount, running balance_after, occurred_at, reason, and the transaction or payment that triggered the entry when applicable.

Use to reconcile top-ups added through POST …/credit or earned through purchases against myne's records.

See glossary: Credit.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
customer_id
required
integer
query Parameters
updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with created_at on or after this instant are returned (compared in UTC, inclusive). Omit for the full list. Invalid values return 400.

Responses

Response samples

Content type
application/json
{
  • "message": "ok",
  • "response": {
    }
}

Points

Brand Points balance, ledger history with reason, and top-up when points are enabled.

Get customer points balance

Return a customer's Brand Points balance and the brand's points label (for example "Stars").

active is false and balance is 0 when Brand Points is not enabled for this brand.

See glossary: Points.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
customer_id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "ok",
  • "response": {
    }
}

Add points to a customer

Add Brand Points to a customer.

Send points_amount and reason in the body. Reason is stored for audit and appears in the points ledger. note is accepted as a legacy alias for reason for one release.

Supply idempotency_key when retrying so duplicate top-ups are not applied. Returns 400 when Brand Points is not enabled for this brand.

See glossary: Points.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
customer_id
required
integer
Request Body schema: application/json
required
points_amount
required
integer

Number of points to add.

amount
integer

Deprecated alias for points_amount.

reason
required
string

Required reason for the top-up (shown in the staff ledger).

note
string

Deprecated alias for reason. Prefer reason.

idempotency_key
string

Optional client-supplied key for safe retries.

Responses

Request samples

Content type
application/json
{
  • "points_amount": 100,
  • "reason": "Compensation for delayed order"
}

Response samples

Content type
application/json
{
  • "message": "ok",
  • "response": {
    }
}

Get customer points ledger

List points ledger entries for a customer, newest first: amount, running balance_after, occurred_at, reason, and the transaction or payment that triggered the entry when applicable.

Empty when Brand Points is not enabled for this brand.

See glossary: Points.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
customer_id
required
integer
query Parameters
updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with created_at on or after this instant are returned (compared in UTC, inclusive). Omit for the full list. Invalid values return 400.

Responses

Response samples

Content type
application/json
{
  • "message": "ok",
  • "response": {
    }
}

Products

Product catalog browse, search, and category metadata—including surface-specific external IDs.

Browse products for a brand

Page through the brand's sellable catalog.

Filter by location_id to include products scoped to one venue (unscoped products still match). Use free-text search to narrow by name or description.

Product rows include partner-safe fields. Use get-by-id or by-external-id when you need integration extended[] payloads—especially surface-specific POS ids before evaluate.

See glossary: Location, Order line pos_id, Surface.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
query Parameters
page
integer >= 1
Default: 1
limit
integer [ 1 .. 100 ]
Default: 20
search
string
location_id
integer

Include products scoped to this location (unscoped products still match).

updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with updated_at on or after this instant are returned (compared in UTC, inclusive). Omit for the full list. Invalid values return 400.

Responses

Response samples

Content type
application/json
{
  • "message": "Products fetched successfully",
  • "response": {
    }
}

Get a product by id

Load one catalog item by myne product_id.

Returns core fields plus extended[] integration payloads (source and external_id per connected app).

Use after browse or when resolving promotion rule references. For register evaluate, pick the extended id that matches your Surface (see Order line pos_id).

See glossary: Order line pos_id, Surface, External source.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
product_id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "Product fetched successfully",
  • "response": {
    }
}

Get a product by external id

Resolve a myne product from your POS or menu external_id without paging browse results.

When source is omitted, lookup uses your Custom API app name (Integrations label). Pass source explicitly to read IDs synced under another integration.

See glossary: external_id and external_data, External source.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
query Parameters
external_id
required
string
source
string

Integration source key; defaults to your credential source.

Responses

Response samples

Content type
application/json
{
  • "message": "Product fetched successfully",
  • "response": {
    }
}

Search products with advanced filters

Search the catalog with a JSON body: optional search text, category_ids, source (integration filter), page, and limit.

Prefer GET /products for simple browse; use this when you need category or source scoping in one request.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
Request Body schema: application/json
required
search
string
category_ids
Array of integers
source
string

Filter to products synced under one integration source.

page
integer >= 1
Default: 1
limit
integer [ 1 .. 100 ]
Default: 20
updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with updated_at on or after this instant are returned (UTC, inclusive).

Responses

Request samples

Content type
application/json
{
  • "search": "string",
  • "category_ids": [
    ],
  • "source": "string",
  • "page": 1,
  • "limit": 20,
  • "updated_since": "2019-08-24T14:15:22Z"
}

Response samples

Content type
application/json
{
  • "message": "Products fetched successfully",
  • "response": {
    }
}

Browse product categories for a brand

Page through product categories for the brand. Optional source filter narrows to categories from one integration.

Each row includes product_count when available. Use category ids in POST /products/search or when reading enriched promotion rules.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
query Parameters
page
integer >= 1
Default: 1
limit
integer [ 1 .. 100 ]
Default: 20
search
string
source
string
updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with updated_at on or after this instant are returned (compared in UTC, inclusive). Omit for the full list. Invalid values return 400.

Responses

Response samples

Content type
application/json
{
  • "message": "Categories fetched successfully",
  • "response": {
    }
}

Get a product category by id

Load one product category by id with product_count.

Returns partner-safe fields; extended[] is reserved for future category integration payloads.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
category_id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "Category fetched successfully",
  • "response": {
    }
}

Promotions

This section covers offers in myne: listing what is set up, checking who can see or use them, and recording a reward on an open sale at a POS or ordering app.

Read the life cycle below first. Then open Evaluate promotions, Apply a promotion, or Complete promotions for the fields of that one call. Linked words open the matching glossary definition.

A Promotion is the offer. A Surface is where the sale happens (register, ordering, join page, and so on). Show vs available is the difference between who can see an offer and who can use it.

Join-page claim is not an API call. Some offers must be claimed on the join page before they can be redeemed. Evaluate still returns those offers, marked unavailable with CLAIM_REQUIRED. Apply and complete reject with the same code. You can list Claimed customer groups and their members; you cannot add members or assign a claim through this API.

Collect Across Venues (venue_unlock) is a passport offer: the same action at each selected site (or each selected child brand under Head office) unlocks a reward. On lsk / lso evaluate, incomplete passports return venue_progress and non_redeemable_cause.code VENUE_UNLOCK_NOT_ELIGIBLE. Browse and get with a child-brand brand_id include Head office Collect Across Venues that target that brand (evaluate-time resolve for this type only — not general Head office promotion sync). Apply and complete use the same promotion id. Stamp brand_id values on venue_progress match ids from brand.organisation on Get credential scope and brand identity or Get brand bootstrap configuration — see Organisation (Head office group).

To list which promotions can show — for the brand catalog or for one customer — without an open order, use Browse promotions, List promotions for a customer, or Search promotions. Optional integration_type on those list calls is only a coarse filter when you do not yet know which app will evaluate the sale (ordering, listing, or ecommerce). It does not replace surface. Do not send integration_type on evaluate, apply, or complete. Those open-order calls always need surface (lsk or lso).

Redeeming on a POS or ordering app

The expected life cycle is: check what fits, take the money off, apply (lock) the reward, then record the redemption when the customer has paid. You take the money off in your POS. myne does not change the ticket.

Use one way to record the redemption:

  • If paid sales from this POS already arrive in myne, mark the order (step 4). When that paid sale arrives, myne records the redemption. Do not send Complete promotions.
  • If paid sales from this POS do not arrive in myne, skip step 4. When the customer has paid, send Complete promotions (step 5).

Follow these five steps in order.

1. Check what fits
Ask which rewards
fit this open order
→ 2. Take the money off
You change the ticket
in your POS
→ 3. Apply (lock the reward)
Send Apply a promotion
for this open order
→ 4. Mark the order
Only if paid sales
already go to myne
→ 5. Record the redemption
When paid: myne records it,
or you send Complete

Before the customer pays, the sale is an open order. After the customer pays, myne can store a Transaction. Recording a promotion redemption does not create that purchase. The purchase is created when the POS or ordering system sends the sale.

1. Check what fits

Call Evaluate promotions while the order is open. We need the Customer (or the id you already synced under your External source), each line’s product id on each line for this Surface, and where you are selling (lsk for register, lso for ordering).

Send your order id as well, so later calls use the same order. myne sends that id back unchanged.

If the offer depends on venue, send a location id that matches how this place of sale names venues.

What happens: myne returns which rewards fit this customer and these lines, and how much to take off. This does not lock a reward.

For Buy X Get Y offers, paid X units are reserved before Y is discounted — Buy 1 Get 1 Free needs two matching units on the order.

2. Take the money off in your POS

You need the discount amount and method from step 1. Apply that change on the ticket in your POS or ordering system. myne does not change the ticket for you.

(Optional: expand the detail block below for how that looks on a register versus ordering.)

3. Apply a promotion (lock the reward)

Call Apply a promotion. We need the same order id as step 1, the customer, the Surface (lsk or lso), and which Promotion they are using (promotion_id).

What happens: the promotion is applied (locked) on this open order. It is not redeemed yet. Points, cashback payment, and the redemption on the customer record wait until step 5. This does not take payment and it does not change the ticket.

Promotion stacking: if the promotions allow it, apply more than one promotion on the same order. Use the same order id each time. One later complete call records every locked reward on that order.

4. Mark the order (only if paid sales already go to myne)

Skip this step if you will send Complete promotions when the customer pays.

If this POS already sends paid sales into myne, mark the open order so myne can match the payment to the locked reward. Write the basket_id and MYNE reference onto the order: prefix MYNE, value = the order id from step 3. Do not write the promotion id.

If you skip this mark and you also skip Complete promotions, the customer can pay and myne will not record the redemption.

5. Record the redemption when the customer has paid

To move from locked to redeemed, use one of these paths:

  • Paid sales already go to myne — you marked the order in step 4. When that paid sale arrives, myne records the redemptions. You do not send Complete promotions.
  • Paid sales do not go to myne — when the customer has paid, call Complete promotions. We need the same order id, the customer, the same surface (lsk or lso), and the paid product lines (not the discount line). One call records every locked reward on that order. Discount amounts in the request are optional and are for reporting only. They do not cause the redemption. If you send the same complete again, myne records nothing extra. If the venue does not match the offer, myne can return success with nothing redeemed.

Recording the redemption does not create the paid purchase in myne. That Transaction is created when the POS or ordering system sends the sale.

Optional detail — how to take money off in the POS

After step 1, myne tells you how to take money off for that place of sale:

  • Register — add a negative-priced promotion product for the discount amount
  • Ordering, whole order — use the POS order-level discount
  • Ordering, line items — use the POS line-level discount
  • Other / not set — take the money off in your own system

The promotion id is not a POS product id. Use it only when you Apply a promotion (step 3).

Next

To list what can show without an open order, open Browse promotions or List promotions for a customer (optional integration_type — customer groups only, no app). For an open order, open Evaluate promotions (step 1), Apply a promotion (step 3), and Complete promotions (step 5, when you record the redemption yourself). Those three always need surface (lsk or lso). Do not send integration_type on them.

Browse promotions for a brand

List promotions configured for a brand.

Filter by location_id, paginate with page and limit, or narrow with search.

Pass surface (connection_pages, meandu, lso, or lsk) when you already know the app. Optional integration_type is only for listing what can show without an open order and without knowing which app will later evaluate the sale: ordering → meandu, listing / ecommerce → connection_pages. Eligibility still follows customer Show vs available groups. Do not send integration_type on evaluate, apply, or complete — those basket calls always need surface (lsk or lso). pos is not a substitute for a register or ordering app.

Each promotion includes image_url (the offer image, or null), availability[] (the surfaces it may appear on) and enriched requirements/targets with product and category names plus extended[].

See glossary: Promotion, Surface, Location.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
query Parameters
location_id
integer

Restrict to promotions for one location (includes brand-wide promotions).

page
integer >= 1
Default: 1
limit
integer [ 1 .. 100 ]
Default: 20
search
string
valid_only
boolean
Default: false

When true, only promotions within their valid date range are returned.

surface
string
Enum: "connection_pages" "meandu" "lso" "lsk" "shopify"

Restrict to promotions visible on one channel.

integration_type
string
Enum: "ordering" "listing" "ecommerce" "pos"

List filter only — not a basket field. Use to return which promotions can show from customer Show vs available groups, in a coarse context (ordering, listing, or ecommerce), without knowing which app will evaluate the sale. Do not send on evaluate, apply, or complete. Those open-order calls always need surface (lsk or lso). ordering → meandu; listing and ecommerce → connection_pages.

updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with updated_at on or after this instant are returned (compared in UTC, inclusive). Omit for the full list. Invalid values return 400.

Responses

Response samples

Content type
application/json
{
  • "message": "Promotions fetched successfully",
  • "response": {
    }
}

List promotions for a customer with eligibility

Return promotions visible to a customer and whether each is redeemable now.

Each row includes eligibility.visibility_state (unlocked or locked) using myne Show vs available customer group rules, plus image_url, availability[] and enriched catalog references.

The response also includes the customer's current points_balance and cashback_balance_in_cents so you do not need a separate points or credit call. Pay with Cashback promotions also include cashback_balance_in_cents on the row (wallet balance, not a cart discount).

Pass surface when you know the app (same meaning as list promotions). Hidden promotions are omitted. Optional integration_type lists what this customer can see from Show vs available groups without an open order and without choosing the evaluate app (ordering, listing, or ecommerce). Do not send it on evaluate, apply, or complete.

See glossary: Promotion, Surface, Show vs available, Customer.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
customer_id
required
integer
query Parameters
valid_only
boolean
Default: true

When true (default), omit expired or not-yet-valid promotions.

surface
string
Enum: "connection_pages" "meandu" "lso" "lsk" "shopify"

Restrict to promotions visible on one channel.

integration_type
string
Enum: "ordering" "listing" "ecommerce" "pos"

List filter only — not a basket field. Use to return which promotions can show from customer Show vs available groups, in a coarse context (ordering, listing, or ecommerce), without knowing which app will evaluate the sale. Do not send on evaluate, apply, or complete. Those open-order calls always need surface (lsk or lso). ordering → meandu; listing and ecommerce → connection_pages.

updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with updated_at on or after this instant are returned (compared in UTC, inclusive). Omit for the full list. Invalid values return 400.

Responses

Response samples

Content type
application/json
{
  • "message": "Customer promotions fetched successfully",
  • "response": {
    }
}

Get a promotion by id

Load one promotion with enrichment.

availability lists the canonical Surfaces it may appear on. image_url is the offer image (null when none is set). Requirements and targets include product and category names plus extended[] resolved from the promotion's rules.

See glossary: Promotion, Surface.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
promotion_id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "Promotion fetched successfully",
  • "response": {
    }
}

Search promotions with advanced filters

Search promotions with filters not available on the browse endpoint: category_ids and product_ids (any match against a promotion's rules), surface, optional integration_type (coarse list filter only — not for basket calls), valid_only, and free-text search.

Each result is enriched the same way as GET …/promotions/{promotion_id}.

See glossary: Promotion, Surface.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
Request Body schema: application/json
required
search
string
location_id
integer
product_ids
Array of integers
category_ids
Array of integers
surface
string
Enum: "connection_pages" "meandu" "lso" "lsk" "shopify"
integration_type
string

List filter only — not a basket field. Use to return which promotions can show from customer Show vs available groups, in a coarse context (ordering, listing, or ecommerce), without knowing which app will evaluate the sale. Do not send on evaluate, apply, or complete. Those open-order calls always need surface (lsk or lso). ordering → meandu; listing and ecommerce → connection_pages.

valid_only
boolean
page
integer >= 1
Default: 1
limit
integer [ 1 .. 100 ]
Default: 20
updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with updated_at on or after this instant are returned (UTC, inclusive).

Responses

Request samples

Content type
application/json
{
  • "search": "string",
  • "location_id": 0,
  • "product_ids": [
    ],
  • "category_ids": [
    ],
  • "surface": "connection_pages",
  • "integration_type": "string",
  • "valid_only": true,
  • "page": 1,
  • "limit": 20,
  • "updated_since": "2019-08-24T14:15:22Z"
}

Response samples

Content type
application/json
{
  • "message": "Promotions fetched successfully",
  • "response": {
    }
}

Check which rewards fit this open order

Step 1 in the Promotions section (Check what fits). This call only returns which rewards fit. It does not lock a reward. Read that life cycle first; this page lists the fields for this call.

We need: who the customer is (customer_id, or an external_id you already synced under your External source), the open-order lines (each with the Order line pos_id for this Surface), and where you are selling (lsk for register, lso for ordering). This is an open-order call: send surface for the app. Do not send integration_type (that field is only for listing promotions without a basket). Send your order id (basket_id and MYNE reference) so later calls use the same order. Send a venue or location id when the offer depends on place.

What happens: myne returns which rewards fit and how much to take off. Each reward includes image_url (the offer image, or null) and a nested promotion. Unavailable rewards include non_redeemable_cause. Join-page claim uses CLAIM_REQUIRED. An exhausted first-X redemption cap uses TOTAL_REDEMPTION_LIMIT_REACHED (POS surfaces keep MAXIMUM_USES_REACHED for the same limit). Next: take the money off in your POS (step 2), Apply a promotion (step 3), then record the redemption when the customer has paid (steps 4–5).

See glossary: Surface, Order line pos_id, basket_id and MYNE reference, External source, external_id and external_data.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
Request Body schema: application/json
required
customer_id
integer

myne customer id (use this or external_id).

external_id
string

Your partner/PMS/CRM id previously synced under your credential External source (for example a CRM id). Resolved when customer_id is omitted (or via customer_source when set). Not email/phone matching. Not used for order-line product matching. Do not pass source on this endpoint.

customer_source
string

Optional External source for customer external_id lookup only. Defaults to your credential source. Never used for order-line pos_id matching.

basket_id
string

Your order id (POS order id or a unique id you generate). myne sends it back unchanged. This does not lock a reward. Reuse the same value on Apply a promotion.

required
object
venue_id
string

Venue id for location-scoped rules on ordering surfaces. Do not use this instead of business_location_id for register (surface=lsk).

business_location_id
string

POS business location id (location.external_location_id in myne). Prefer for surface=lsk (register).

surface
string
Enum: "connection_pages" "meandu" "lso" "lsk" "shopify"

Channel for this open order. Send lsk (register) or lso (ordering). Do not send integration_type on this basket call. lsk/meandu/lso are forwarded to the rewards engine as source.

order_type
string
Enum: "pickup" "delivery" "dine_in"

Optional fulfillment type for this open order (pickup, delivery, or dine_in). Omit it and unrestricted promotions still evaluate. A promotion restricted to order types is not eligible when this is omitted or does not match (ORDER_TYPE_REQUIRED or ORDER_TYPE_MISMATCH on that reward, not a failed call). Any other value returns 400. Bopple maps their types to these three: ASAP / Scheduled / Catering Pickup → pickup; ASAP / Scheduled / Catering Delivery → delivery; Dine in / Room Service / Order to seat → dine_in. Web, App, and Kiosk stay as surface, not order_type.

Responses

Request samples

Content type
application/json
Example
{
  • "customer_id": 104823,
  • "surface": "lsk",
  • "basket_id": "pos-order-7f3a2c",
  • "business_location_id": "loc-sydney-01",
  • "cart": {
    }
}

Response samples

Content type
application/json
Example
{
  • "message": "Promotions evaluated successfully",
  • "response": {
    }
}

Apply a promotion (lock the reward on this open order)

This is Apply a promotion — step 3 in the Promotions section (Lock the reward). This call applies the chosen promotion to the open order (locks it). It does not take money off the ticket (step 2) and it does not record the redemption (step 5). Read that life cycle first; this page lists the fields for this call.

We need: the Surface (lsk for register, lso for ordering), who the customer is (customer_id, or an external_id you already synced under your External source), and which Promotion they are using (promotion_id). This is an open-order call: send surface for the app. Do not send integration_type. Send the same order id (basket_id and MYNE reference) from step 1 when you have one. Send a venue or location id when the offer depends on place.

What happens: myne returns the order id to keep using (basket_id; if you omitted it, this is myne’s selection_id). The promotion is applied (locked), not redeemed. If the offer must be claimed on the join page first, apply rejects with code CLAIM_REQUIRED. If the first-X redemption cap is gone, apply rejects with TOTAL_REDEMPTION_LIMIT_REACHED. Then either mark the order so myne records the redemption when the paid sale arrives (steps 4–5), or send Complete promotions when the customer has paid (skip step 4).

Promotion stacking is covered in the Promotions life cycle (step 3).

See glossary: basket_id and MYNE reference, Promotion stacking, Surface, Promotion, External source.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
Request Body schema: application/json
required
customer_id
integer

myne customer id (use this or external_id).

external_id
string

Your partner/PMS/CRM id under your credential External source (for example a CRM id). Resolved when customer_id is omitted (or via customer_source when set).

customer_source
string

Optional External source for customer external_id lookup only. Defaults to your credential source.

promotion_id
required
integer

Promotion to apply (lock) on the open order (from evaluate or catalog).

basket_id
string

Your order id (POS order id or a unique id you generate). Field name remains basket_id. Reuse the same value on every apply for this open order, then on Complete promotions or on the MYNE order mark.

surface
required
string
Enum: "lsk" "lso"

Where this open order is sold. Required. Send lsk (register) or lso (ordering) — the same value as evaluate. Apply can lock a reward only on those two surfaces, not join page, meandu, or shopify. When surface=lsk, the response includes MYNE mark details if paid sales already go to myne.

location_id
integer

myne location id when the offer depends on place.

venue_id
string

Venue id for location-scoped rules on ordering. Do not use this instead of business_location_id for register (surface=lsk).

business_location_id
string

POS business location id (location.external_location_id in myne). Prefer for surface=lsk (register).

order_type
string
Enum: "pickup" "delivery" "dine_in"

Optional fulfillment type for this open order (pickup, delivery, or dine_in). Omit it and unrestricted promotions still evaluate. A promotion restricted to order types is not eligible when this is omitted or does not match (ORDER_TYPE_REQUIRED or ORDER_TYPE_MISMATCH on that reward, not a failed call). Any other value returns 400. Bopple maps their types to these three: ASAP / Scheduled / Catering Pickup → pickup; ASAP / Scheduled / Catering Delivery → delivery; Dine in / Room Service / Order to seat → dine_in. Web, App, and Kiosk stay as surface, not order_type.

Responses

Request samples

Content type
application/json
{
  • "customer_id": 104823,
  • "promotion_id": 901,
  • "surface": "lsk",
  • "basket_id": "pos-order-7f3a2c"
}

Response samples

Content type
application/json
{
  • "message": "Promotion applied to open order successfully",
  • "response": {
    }
}

Record the redemption after the customer has paid

Step 5 in the Promotions section (Record the redemption when the customer has paid), when paid sales from this POS do not already arrive in myne. Skip the order mark (step 4). Read that life cycle first; this page lists the fields for this call.

We need: the same basket_id from apply, who the customer is, the Surface (lsk or lso), and the paid product lines (each with the Order line pos_id — not the discount line). This is an open-order call: send surface for the app. Do not send integration_type. Optional discounts[] amounts are for reporting only. They do not cause the redemption. One call records every locked reward on that order.

What happens: myne records the redemptions and clears the lock. A later POS or ordering sale for the same cart does not redeem again. If nothing is still locked, redeemed_count is 0. Complete does not create Claimed-group membership. If a locked offer still requires join-page claim, complete rejects with CLAIM_REQUIRED instead of recording. Recording the redemption does not create the paid purchase in myne. That purchase is created when the POS or ordering system sends the sale.

See glossary: basket_id and MYNE reference, Surface, Transaction.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
Request Body schema: application/json
required
customer_id
integer

myne customer id (use this or external_id).

external_id
string

Your partner/PMS/CRM id under your credential External source. Resolved when customer_id is omitted (or via customer_source when set).

customer_source
string

Optional External source for customer external_id lookup only. Defaults to your credential source.

basket_id
required
string

Required. Same open-order id returned from apply (or the partner id you sent on apply).

surface
required
string
Enum: "lsk" "lso"

Where you sold. Required. Must be the same lsk (register) or lso (ordering) value used on evaluate and apply.

required
object

Paid product lines sold on this order (not the discount line). Same line shape as evaluate. We need these lines to record the redemption.

location_id
integer

myne location id when the offer depends on place.

venue_id
string

Optional venue id for location-scoped rules.

business_location_id
string

POS business location id (location.external_location_id in myne).

order_type
string
Enum: "pickup" "delivery" "dine_in"

Optional fulfillment type for this open order (pickup, delivery, or dine_in). Omit it and unrestricted promotions still evaluate. A promotion restricted to order types is not eligible when this is omitted or does not match (ORDER_TYPE_REQUIRED or ORDER_TYPE_MISMATCH on that reward, not a failed call). Any other value returns 400. Bopple maps their types to these three: ASAP / Scheduled / Catering Pickup → pickup; ASAP / Scheduled / Catering Delivery → delivery; Dine in / Room Service / Order to seat → dine_in. Web, App, and Kiosk stay as surface, not order_type.

Array of objects

Optional amounts already taken off the paid order, for reporting only. Omit if you do not have amounts. Does not cause the redemption.

Responses

Request samples

Content type
application/json
{
  • "customer_id": 104823,
  • "basket_id": "pos-order-7f3a2c",
  • "surface": "lsk",
  • "location_id": 12,
  • "cart": {
    },
  • "discounts": [
    ]
}

Response samples

Content type
application/json
Example
{
  • "message": "Promotions completed for this order successfully",
  • "response": {
    }
}

Transactions

Paid purchase history and line-item detail for customers. An open sale is an order. After the customer pays, myne can store a transaction. Purchases are created when the POS or ordering system sends the sale. Recording a promotion redemption does not create a purchase.

List transactions for a customer

Page through paid purchase history for one customer. An open sale is an order; once paid it becomes a Transaction. Returns POS and payment-linked transactions with line items.

Use limit and offset (or page) for pagination. Set payments=true to include payment detail on each row.

Customer events and CRM activities are separate endpoints—see Activities and POST …/events. Returns 404 when the customer is not in this brand.

See glossary: Customer, Transaction, Activity.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
customer_id
required
integer
query Parameters
limit
integer [ 1 .. 100 ]
Default: 25
offset
integer [ 0 .. 10000 ]
Default: 0
page
integer >= 1
Default: 1
payments
boolean

When true, include payment detail on each transaction.

updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with updated_at on or after this instant are returned (compared in UTC, inclusive). Omit for the full list. Invalid values return 400.

Responses

Response samples

Content type
application/json
{
  • "message": "Transactions fetched successfully",
  • "response": {
    }
}

Get a transaction by id

Load one paid Transaction for the brand, including line items and payment rows.

Use after listing customer transactions or searching brand-wide. Returns 404 when the transaction is not in this brand.

See glossary: Transaction.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
transaction_id
required
integer
query Parameters
payments
boolean
Default: true

When false, omit payment rows from the response.

Responses

Response samples

Content type
application/json
{
  • "message": "Transaction fetched successfully",
  • "response": {
    }
}

Search transactions with filters

Search brand transactions (paid orders) with a JSON body: optional customer_id, location_id, date range (transacted_from / transacted_to), min_amount and max_amount (total paid), plus page, limit, and payments=true for payment detail.

Prefer the customer-scoped list when you already have customer_id.

See glossary: Transaction.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
Request Body schema: application/json
required
customer_id
integer
location_id
integer
transacted_from
string <date-time>
transacted_to
string <date-time>
date_from
string <date-time>

Alias for transacted_from.

date_to
string <date-time>

Alias for transacted_to.

min_amount
number
max_amount
number
payments
boolean
page
integer >= 1
Default: 1
limit
integer [ 1 .. 100 ]
Default: 25
offset
integer >= 0
Default: 0
updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with updated_at on or after this instant are returned (UTC, inclusive).

Responses

Request samples

Content type
application/json
{
  • "customer_id": 0,
  • "location_id": 0,
  • "transacted_from": "2019-08-24T14:15:22Z",
  • "transacted_to": "2019-08-24T14:15:22Z",
  • "date_from": "2019-08-24T14:15:22Z",
  • "date_to": "2019-08-24T14:15:22Z",
  • "min_amount": 0,
  • "max_amount": 0,
  • "payments": true,
  • "page": 1,
  • "limit": 25,
  • "offset": 0,
  • "updated_since": "2019-08-24T14:15:22Z"
}

Response samples

Content type
application/json
{
  • "message": "Transactions fetched successfully",
  • "response": {
    }
}

Activities

CRM activity feed and manual notes on contacts—distinct from Customer events writes.

List manual activity type labels

Return activity type labels for CRM dropdowns: the standard library (Call, Email, Meeting, Note, Site visit, Demo, Proposal, Contract, Follow-up, Support) merged with any custom labels already used on this brand (staff or Connect).

Use before POST …/activities/manual.

Customer events (POST …/events) are integration timeline writes. Activities are the CRM feed, including manual notes.

See glossary: Activity.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "Manual activity types fetched successfully",
  • "response": {
    }
}

List activities for a customer

Page through the CRM activity feed for one customer—manual notes, reservations, task-linked entries, and integration-sourced rows.

Optional query filters: activity_type (or type) and source. For date ranges or brand-wide search, use POST …/activities/search.

Not the same as POST …/events, which appends integration timeline events. Paginate with limit and offset (or page). Returns 404 when the customer is not in this brand.

See glossary: Activity.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
customer_id
required
integer
query Parameters
limit
integer [ 1 .. 100 ]
Default: 25
offset
integer [ 0 .. 10000 ]
Default: 0
page
integer >= 1
Default: 1
activity_type
string

Match event_name or manual activity_type label (e.g. Call).

type
string

Alias for activity_type.

source
string

Filter by event source (e.g. business_manual or your integration source).

updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with updated_at on or after this instant are returned (compared in UTC, inclusive). Omit for the full list. Invalid values return 400.

Responses

Response samples

Content type
application/json
{
  • "message": "Activities fetched successfully",
  • "response": {
    }
}

Record a manual CRM activity

Add a manual note or call log to the customer CRM feed without staff login.

Requires title, or both activity_type and notes. Prefer activity_type values from GET …/activities/manual-types.

Optional business_id when the contact is linked to a business account; event_time defaults to now. The activity is attributed to your API credential source and label. Do not send source in the body.

See glossary: Activity, Business, External source.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
customer_id
required
integer
Request Body schema: application/json
required
title
string
activity_type
string
notes
string
event_time
string <date-time>
business_id
integer

Responses

Request samples

Content type
application/json
{
  • "title": "string",
  • "activity_type": "string",
  • "notes": "string",
  • "event_time": "2019-08-24T14:15:22Z",
  • "business_id": 0
}

Response samples

Content type
application/json
{
  • "message": "Manual activity recorded successfully",
  • "response": {
    }
}

Search activities with filters

Search the CRM activity feed with a JSON body: optional customer_id, business_id, activity_type (or type), source, date range (event_from / event_to), plus page and limit.

Customer events (POST …/events) are integration timeline writes; this endpoint reads the broader CRM feed.

See glossary: Activity.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
Request Body schema: application/json
required
customer_id
integer
business_id
integer
activity_type
string
type
string

Alias for activity_type.

source
string
event_from
string <date-time>
event_to
string <date-time>
date_from
string <date-time>

Alias for event_from.

date_to
string <date-time>

Alias for event_to.

page
integer >= 1
Default: 1
limit
integer [ 1 .. 100 ]
Default: 25
offset
integer >= 0
Default: 0
updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with updated_at on or after this instant are returned (UTC, inclusive).

Responses

Request samples

Content type
application/json
{
  • "customer_id": 0,
  • "business_id": 0,
  • "activity_type": "string",
  • "type": "string",
  • "source": "string",
  • "event_from": "2019-08-24T14:15:22Z",
  • "event_to": "2019-08-24T14:15:22Z",
  • "date_from": "2019-08-24T14:15:22Z",
  • "date_to": "2019-08-24T14:15:22Z",
  • "page": 1,
  • "limit": 25,
  • "offset": 0,
  • "updated_since": "2019-08-24T14:15:22Z"
}

Response samples

Content type
application/json
{
  • "message": "Activities fetched successfully",
  • "response": {
    }
}

Tasks

Staff follow-up tasks: browse, get, and search by assignee, due date, status, business, or customer.

Browse tasks for a brand

Page through staff tasks for the brand. Defaults to open work (todo and in_progress) sorted by most recently updated.

Filter with query parameters: status or statuses, exclude_statuses, assignee_user_ids, assignee_filter (e.g. unassigned), due_date_filter, business_id, customer_id, free-text query, sort_by, and sort_dir.

Partner-safe fields only—assignee and customer emails are omitted.

See glossary: Task.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
query Parameters
page
integer >= 1
Default: 1
limit
integer [ 1 .. 100 ]
Default: 20
query
string

Free-text search on title and linked record names.

status
string
Enum: "todo" "in_progress" "complete" "parked"
statuses
string

Comma-separated status values.

exclude_statuses
string

Comma-separated statuses to omit.

assignee_user_ids
string

Comma-separated myne user IDs.

assignee_filter
string
Value: "unassigned"

Special assignee filter. Use unassigned for tasks with no assignee.

due_date_filter
string
Enum: "today" "tomorrow" "this_week" "past" "upcoming" "no_due_date"
business_id
integer
customer_id
integer
sort_by
string
Default: "updated_at"
Enum: "title" "status" "due_date" "updated_at"
sort_dir
string
Default: "desc"
Enum: "asc" "desc"
updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with updated_at on or after this instant are returned (compared in UTC, inclusive). Omit for the full list. Invalid values return 400.

Responses

Response samples

Content type
application/json
{
  • "message": "Tasks fetched successfully",
  • "response": {
    }
}

Get a task by id

Load one task with linked customers, businesses, locations, assignees, and optional status/comment updates.

Set include_updates=false to omit the updates array. Returns 404 when the task is not in this brand.

See glossary: Task.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
task_id
required
integer
query Parameters
include_updates
boolean
Default: true

When false, omit the updates array from the response.

Responses

Response samples

Content type
application/json
{
  • "message": "Task fetched successfully",
  • "response": {
    }
}

List tasks for a customer

Page through tasks linked to one customer (contact). Uses the same pagination fields as brand task browse.

Useful when syncing follow-ups from your CRM back to myne or displaying open work on a contact profile.

See glossary: Task, Customer.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
customer_id
required
integer
query Parameters
page
integer >= 1
Default: 1
limit
integer [ 1 .. 100 ]
Default: 20
updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with updated_at on or after this instant are returned (compared in UTC, inclusive). Omit for the full list. Invalid values return 400.

Responses

Response samples

Content type
application/json
{
  • "message": "Customer tasks fetched successfully",
  • "response": {
    }
}

Search tasks with advanced filters

Search tasks with a JSON body: assignee_user_ids, assignee_filter, status or statuses, exclude_statuses, due_date_filter, business_id, customer_id, free-text query, sort_by, sort_dir, page, and limit.

Prefer GET …/tasks for the default open/recent browse; use this when you need richer filters in one request.

Creating tasks via Connect is not available yet.

See glossary: Task.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
Request Body schema: application/json
required
query
string
search
string

Alias for query.

status
string
Enum: "todo" "in_progress" "complete" "parked"
statuses
Array of strings
exclude_statuses
Array of strings
assignee_user_ids
Array of integers
assignee_filter
string
Value: "unassigned"

Special assignee filter. Use unassigned for tasks with no assignee.

due_date_filter
string
Enum: "today" "tomorrow" "this_week" "past" "upcoming" "no_due_date"
business_id
integer
customer_id
integer
sort_by
string
Enum: "title" "status" "due_date" "updated_at"
sort_dir
string
Enum: "asc" "desc"
page
integer >= 1
Default: 1
limit
integer [ 1 .. 100 ]
Default: 20
updated_since
string <date-time>

ISO-8601 timestamp. When set, only rows with updated_at on or after this instant are returned (UTC, inclusive).

Responses

Request samples

Content type
application/json
{
  • "query": "string",
  • "search": "string",
  • "status": "todo",
  • "statuses": [
    ],
  • "exclude_statuses": [
    ],
  • "assignee_user_ids": [
    ],
  • "assignee_filter": "unassigned",
  • "due_date_filter": "today",
  • "business_id": 0,
  • "customer_id": 0,
  • "sort_by": "title",
  • "sort_dir": "asc",
  • "page": 1,
  • "limit": 20,
  • "updated_since": "2019-08-24T14:15:22Z"
}

Response samples

Content type
application/json
{
  • "message": "Tasks fetched successfully",
  • "response": {
    }
}

Businesses

Browse and retrieve B2B business profiles and extended data.

Get a business by external id

Resolve a myne business account from your external_id without paging browse results.

When source is omitted, lookup uses your Custom API app name (Integrations label). Pass source explicitly to read IDs synced under another integration.

Returns 404 when no match exists for this brand.

See glossary: Business, external_id and external_data, External source.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
query Parameters
external_id
required
string

Your integration's identifier for the business.

source
string

Origin system for the external_id. When omitted, defaults to your Custom API app name (Integrations label). Read-only filter for cross-integration lookups.

Responses

Response samples

Content type
application/json
{
  • "message": "Business fetched successfully",
  • "response": {
    }
}

Browse businesses for a brand

Page through business (B2B) accounts for a brand. Use page and limit for pagination and query for free-text search.

Pass updated_since (ISO-8601, compared in UTC) to poll only businesses changed on or after that timestamp.

Business IDs from here or sync batch can be passed to the single-business and extended endpoints.

See glossary: Business.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
query Parameters
page
integer >= 1
Default: 1
limit
integer [ 1 .. 100 ]
Default: 10
query
string

Free-text search across business fields.

updated_since
string <date-time>

ISO-8601 timestamp. When set, only businesses with updated_at on or after this instant are returned (compared in UTC).

Responses

Response samples

Content type
application/json
{
  • "message": "Business records fetched successfully",
  • "response": {
    }
}

Get a business by id

Load one business account by ID.

Use after browse or sync when you need core fields such as name, email, and phone.

See glossary: Business.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
business_id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "Business fetched successfully",
  • "response": {
    }
}

Get extended business profile

Fetch extended business data: custom properties, linked contacts, and other metadata beyond the core business row.

Use when your integration needs the full CRM picture for a company account.

See glossary: Business, Extended profile.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
business_id
required
integer

Responses

Response samples

Content type
application/json
{
  • "message": "Business extended data fetched successfully",
  • "response": [
    ]
}

Sync

Batch upsert contacts, businesses, business–contact links, and extended metadata.

Batch upsert contacts, businesses, and links

Push up to 50 contacts, businesses, business–contact links, extended fields, or health topics in one request.

This is the primary write path for CRM, PMS, and POS integrations syncing data into myne (for example guests from MEWS).

Send top-level contact fields plus your external_id, and optionally contact_extended bodies for extra partner keys/metadata used later for lookup and enrichment.

Records are always stamped with your Custom API app name—do not send source (or contact_source / business_source) in item bodies.

Each item has a type and body; see the request schema for supported types.

See glossary: Sync batch, External source, external_id and external_data.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
Request Body schema: application/json
required
required
Array of objects <= 50 items

Responses

Request samples

Content type
application/json
{
  • "items": [
    ]
}

Response samples

Content type
application/json
{
  • "message": "Batch upsert complete",
  • "response": {
    }
}

CRM Embed

Mint short-lived tokens to load CRM embed widgets in your app.

Mint a short-lived Bearer token for CRM embed

Create a short-lived Bearer token (15 minutes) to load myne CRM embed widgets for one customer or business.

Call from your server after Basic auth. Pass entity_type (customer or business) and entity_id in the body, then use embed_token in the widget bootstrap.

See glossary: CRM embed, Customer, Business.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
Request Body schema: application/json
required
entity_type
required
string
Enum: "customer" "business"
entity_id
required
integer

Responses

Request samples

Content type
application/json
{
  • "entity_type": "customer",
  • "entity_id": 0
}

Response samples

Content type
application/json
{
  • "response": {
    }
}

Webhooks

Subscribe HTTPS destinations to brand events. Signing secret is returned only on create and rotate. Verify X-Myne-Signature with HMAC-SHA256 over {unix_ts}.{rawBody} using crypto.timingSafeEqual. Use X-Myne-Delivery-Id for idempotency. Poll collection GETs with updated_since when you prefer pull.

List outbound webhook subscriptions

List HTTPS destinations this Custom API app created for brand events.

Signing secrets are never returned on list or get. Copy the secret when you create or rotate.

Staff can also manage the same rows in Settings → Webhooks → Outgoing.

See glossary: Outbound webhook, API Credentials.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer

Responses

Create an outbound webhook subscription

Subscribe an HTTPS URL to one or more brand event topics.

The signing secret is returned once. Store it and verify X-Myne-Signature with HMAC-SHA256 over {unix_ts}.{rawBody} using crypto.timingSafeEqual. Also send X-Myne-Topic and X-Myne-Delivery-Id (use delivery_id for idempotency).

URL must be HTTPS and must not resolve to private, loopback, link-local, or metadata addresses. Default ignore_own_writes is true so events this app wrote are not echoed back.

See glossary: Outbound webhook, Signature.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
Request Body schema: application/json
required
label
string
url
required
string <uri>
topics
required
Array of strings
Items Enum: "customer.created" "customer.updated" "transaction.completed" "customer.added_to_group" "customer.removed_from_group" "customer.connected" "customer.form_submitted" "promotion.redeemed" "customer_activity.created" "customer_activity.updated"
ignore_own_writes
boolean
Default: true

Responses

Request samples

Content type
application/json
{
  • "label": "string",
  • "topics": [
    ],
  • "ignore_own_writes": true
}

List outbound webhook topics

Return the topic catalog you can subscribe to: customer.created, customer.updated, transaction.completed, customer.added_to_group, customer.removed_from_group, customer.connected, customer.form_submitted, promotion.redeemed, customer_activity.created, customer_activity.updated.

The customer.created and customer.updated payloads include connection_type — connected when the customer has joined loyalty, known when myne has the customer but they have not joined, and unknown for an anonymous website visitor. It matches the connection_type on the customer list and get-customer endpoints.

Unknown topic names on create or update return 400.

See glossary: Outbound webhook.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer

Responses

Get an outbound webhook subscription

Load one destination this app owns. The signing secret is not included.

See glossary: Outbound webhook.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
webhook_id
required
integer

Responses

Update an outbound webhook subscription

Change label, URL, topics, status (enabled or disabled), or ignore_own_writes.

Does not return a new signing secret. Use rotate for that.

See glossary: Outbound webhook.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
webhook_id
required
integer

Responses

Rotate the outbound webhook signing secret

Replace the HMAC signing secret. The new secret is returned once and cannot be shown again.

See glossary: Outbound webhook, Signature.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
webhook_id
required
integer

Responses

Remove an outbound webhook subscription

Soft-delete this destination. Delivery stops. This app can only remove rows it created.

See glossary: Outbound webhook.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
webhook_id
required
integer

Responses

Send a signed ping to the destination

POST a sample Connect-shaped envelope to the destination URL with the same signature headers as live events, and write a delivery row.

See glossary: Outbound webhook, Signature.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
webhook_id
required
integer

Responses

List recent outbound webhook deliveries

Recent delivery attempts for this subscription: status, HTTP code, topic, delivery_id, and a truncated error. Payloads and signing secrets are not stored.

See glossary: Outbound webhook.

Authorizations:
basicAuthbearerAuth
path Parameters
brand_id
required
integer
webhook_id
required
integer

Responses