Configuration
Your integration declares a configuration schema (config_schema). ShopiMind automatically generates the corresponding form in the interface; the values entered are passed to you (decrypted) in the activate and config_updated webhooks.
Flat schema
{
"fields": [
{ "key": "api_url", "type": "url", "required": true, "label": "API URL" },
{ "key": "api_token", "type": "password", "required": true, "label": "Token" },
{ "key": "list_id", "type": "select", "required": false, "label": "List",
"options": [{ "value": "vip", "label": "VIP" }, { "value": "all", "label": "All" }] }
]
}Field types
text · password · textarea · email · url · number · select · multiselect · checkbox.
Possible validation rules: minLength / maxLength / pattern (text), min / max / step (number).
Sensitive fields
The password / secret / token fields are encrypted at rest on the ShopiMind side. They are passed to you decrypted in activate / config_updated, never exposed anywhere else.
Multi-step schema
For configurations that happen in several stages (e.g. entering credentials, then choosing a list that depends on those credentials):
{
"steps": [
{
"key": "credentials",
"label": "Credentials",
"fields": [
{ "key": "api_url", "type": "url", "required": true },
{ "key": "api_token", "type": "password", "required": true }
],
"on_complete": { "action": "test_connection" }
},
{
"key": "mapping",
"label": "Mappings",
"fields": [
{ "key": "list_id", "type": "select", "required": true }
]
}
]
}- Partial saving (step by step) is allowed.
- With
on_complete: { action: "test_connection" }, the step is only considered valid after a successful connection test. Modifying a field of a validated step invalidates its validation. - Completeness of all steps is required at activation.
test_connection
When the user validates a step with on_complete: test_connection (or clicks "Test"), ShopiMind sends a signed webhook to the test_connection URL you declared. The body is the config map (decrypted), without an event envelope:
{ "api_url": "https://...", "api_token": "..." }Respond (HTTP 200) with:
{ "success": true }or
{ "success": false, "error": "Unable to reach the service" }remote-data/<resource> — dynamic lists
To populate a select / multiselect with values coming from your system (e.g. the list of segments of the connected account), declare a webhook URL named after the resource. ShopiMind calls it (signed webhook, body = configs) and expects:
{
"data": [
{ "value": "list_42", "label": "VIP Customers" },
{ "value": "list_7", "label": "Newsletter" }
]
}The user then sees label, and value is stored as the field's value.
Declaring your webhooks
ShopiMind maps each event (and each remote-data resource) to a URL on your server. You provide these URLs and your HMAC secret to ShopiMind when registering your integration:
{
"install": "https://your-host/webhook/receive",
"uninstall": "https://your-host/webhook/receive",
"activate": "https://your-host/webhook/receive",
"deactivate": "https://your-host/webhook/receive",
"config_updated": "https://your-host/webhook/receive",
"test_connection": "https://your-host/webhook/test-connection",
"your_resource": "https://your-host/webhook/remote-data/your_resource"
}Integrator config (owner: "integrator")
A config_schema field can be marked owner: "integrator": it is not shown to the merchant — the integrator sets its value per shop, via the API, with its integration API key. The value resolves at render as {integration.<key>} (with the declared default as fallback until it's set).
Handy for an integrator-specific but shop-specific value: a tracking URL, an account id, a computed API base, etc.
// in config_schema.fields (or steps[].fields)
{ "key": "tracking_base", "type": "text", "owner": "integrator", "default": "https://t.partner.io/p" }Set / read the values via the SDK (with the integration's API key):
const { SpmIntegrationConfig } = require('@shopimind/sdk-shopimind');
await SpmIntegrationConfig.set(client, { tracking_base: 'https://t.partner.io/p' });
const res = await SpmIntegrationConfig.get(client); // res.data.data.values = { tracking_base: '…' }Or raw HTTP: PUT /v1/integration-config (body = { <key>: <value> }) and GET /v1/integration-config. Only keys declared owner: "integrator" are accepted; the merchant can never change them, and they never flow into an image URL (non-sensitive values, resolved as {integration.*}).