Custom data
ShopiMind custom data lets you model business objects specific to your activity — negotiated prices, dedicated account managers, specific contracts, business tracking — and make them immediately usable in the platform: segmentation, filters, scenario triggers, dynamic message content.
A two-level model
The API draws a clear line between the schema (what you model) and the records (the values).
Custom data definitions — the schemas
A definition declares the structure of a custom object:
- A
name(the label shown in the ShopiMind dashboard). - A list of typed
fields(string,number,date,boolean,list). - An optional uniqueness key (
unique_keys) — used bysaveCustomDataRecordsto resolve upserts. - Optional
relationshipslinking a source field to another resource (a system schema such ascontactsorproducts, or another custom definition).
→ Reference: createCustomDataDefinition
Custom data records — the values
Once a definition is created, you push records into it: rows of data that follow the declared schema. The endpoint accepts batches (up to 50 per call) and upserts on the uniqueness key when defined.
→ Reference: saveCustomDataRecords
Relations
A field on a definition can be declared as a relation to another resource. Three target types are supported:
contacts(system schema) — to link a record to a ShopiMind contact.products(system schema) — to link a record to a catalog product.- another custom data definition — to model composite objects (e.g. a loyalty program references an account manager).
A definition can combine several relations — for example, "vet visit" references both a contact (the owner) and a product (the service consumed).
Reference a contact from a record
Customers vs. contacts
Before going further, keep in mind the distinction between customers (pushed by your integration) and contacts (unified profiles generated by ShopiMind). Custom records are attached to contacts, not customers — see Customers and contacts.
For a field declared as a relation to the contacts system schema, the API accepts three identifiers to designate the target contact — without pre-resolution on your side.
Three supported identifiers
by | Description | Type |
|---|---|---|
id_contact | The ShopiMind contact identifier (legacy). | number |
email | The contact's email. | string |
id_customer | Your shop-side customer ID (id_customer_shop). | string |
Whichever identifier you send, the database always stores the canonical id_contact. Resolution is transparent.
Two accepted formats
Direct format (backwards-compatible) — you send the ShopiMind id_contact as-is:
{
"contact_id": 12345,
"points": 450,
"tier": "gold"
}Object format { by, value } — you send whichever identifier you have on hand, the server resolves it:
{
"contact_id": { "by": "email", "value": "marie.dupont@example.com" },
"points": 450,
"tier": "gold"
}You can mix both formats within the same batch: one record with a direct id_contact, the next with an email, the third with an id_customer. Each type is resolved with a single grouped SQL query.
Which identifier to use
| You have… | Recommended identifier |
|---|---|
| An export from your DB with your own ID | id_customer |
| A trigger based on email signup | email |
| A ShopiMind workflow that handed the ID | id_contact |
| A mixed CSV import | Mix within the batch |
Common errors
- Contact not found — if the
emailorid_customeryou send doesn't match any contact, the item is rejected with a400error indicating its position in the batch and details (resolution is strict, it doesn't create the contact on the fly). - Unsupported identifier —
byonly acceptsid_contact,email,id_customerfor relations tocontacts. - Duplicate emails — atypical case: if multiple shop contacts share the same email, resolution returns one of them with no guaranteed order. Prefer
id_customerorid_contactwhen you need a strict 1-1 guarantee.
Override of native fields (product prices)
A definition can override a system field. Today, this is mostly used for price: the same product can display a different price depending on the connected contact — B2B pricing, negotiated price, loyalty-tier-based pricing.
Up to three priority sources per overridden field. The resolution rule is deterministic: priority: 1 (highest) wins on tie.
→ Concrete use case: Veterinary pricing.
Usage on the ShopiMind side
Once ingested, records (and their relations) are available in:
- Segmentation: build a segment "contacts whose
loyalty.tier = gold". - Scenario filters: "if the contact had at least one vet visit this year".
- Dynamic content: inject
{var=loyalty.points_balance}in an email. - Triggers: fire a scenario when a record is created or updated.
Typical workflow
- Model the definition on your back-office (list the fields, identify the relations, define the uniqueness key).
- Create the definition via the API (
createCustomDataDefinition). - Capture the returned
id_definition. - Push the associated records via
saveCustomDataRecords, referencing thisid_definition. - Use the data from the ShopiMind dashboard (segmentation, scenarios, content).
Limits to know
- Shop-scoped definitions — each definition is tied to a single shop, no sharing across shops within an account.
- Override — currently limited to
products.priceandproducts.price_discount, three priority sources max per field. - Inactive definition = read-only — an
inactivedefinition rejects every write (saveCustomDataRecords,updateCustomDataRecord,deleteCustomDataRecord). Existing records remain readable. - Maximum batch size — 50 records per call for
saveCustomDataRecords, 20 forbulkDeleteCustomDataRecords.
Going further
- Use cases with custom data — veterinary pricing, dedicated account manager.
- API reference: Custom data definitions and Custom data records.