Integration Sync API
Overview
Section titled “Overview”The Integration Sync API connects a MicroPIM account to a storefront (for example a Shopify shop) and pushes product data from MicroPIM to it. It is used by storefront connectors that need to create and manage an integration, monitor its health, and push batches of products.
This API is distinct from the core Product API, which is used for reading and writing product data directly against MicroPIM. If you only need to manage products in MicroPIM itself, use the core Product API instead.
MicroPIM syncs product data only — products, variants, SKUs, prices, stock/inventory levels, categories, brands, images, attributes, and SEO fields. MicroPIM does not sync orders or customers, and no endpoint on this page returns or accepts order or customer data.
Key differences from the core Product API
Section titled “Key differences from the core Product API”| Core Product API | Integration Sync API | |
|---|---|---|
| Auth header | X-API-KEY | Authorization: Bearer <api_token> |
| Envelope | {"status": 1, "data": ..., "error": null} | {"status": "success", "message": "...", "data": {...}, "code": "..."} |
| Purpose | Read/write product data directly | Connect a storefront, monitor sync health, push product batches |
| Reference | /reference/rest-api/ | This page |
Authentication
Section titled “Authentication”Most endpoints require a bearer token sent via the Authorization header:
curl -H "Authorization: Bearer a1b2c3d4..." https://app.micropim.net/api/statusThe token (api_token) is issued by POST /api/connect and returned as data.api_token. It is an opaque string, not a JWT.
Tokens carry a scope, which maps to a role required by each endpoint:
| Scope | Role |
|---|---|
read | ROLE_API_READ |
write | ROLE_API_WRITE |
admin | ROLE_API_ADMIN |
A few endpoints (POST /api/connect, GET /api/status/{integrationId}, GET /api/system/status) are public and require no token.
Requests with a missing or invalid token return 401 Unauthorized.
Response envelope
Section titled “Response envelope”Most endpoints return an enveloped JSON body:
{ "status": "success", "message": "Human-readable message", "data": { }, "code": null}statusis one of"success","error", or"partial"(used only byproducts/pushwhen some items in a batch fail).- On success,
codeis typically absent ornull. - On error,
codeis a machine-readable string (see Error codes) anddatais typically absent.
Two endpoints are an exception and return a raw, non-enveloped JSON object — there is no status/data wrapper:
GET /api/status/{integrationId}returns a flat object with fields directly at the top level.GET /api/system/statusreturns{"status": "operational", "timestamp": "...", "stats": {...}}(herestatusis a plain health string, not the envelope’s success/error/partial status).
Keep this inconsistency in mind when parsing responses — check which endpoint you called before assuming the envelope shape.
Timestamps also differ in format by endpoint:
Y-m-d H:i:s(e.g."2026-07-16 10:30:00") — used byconnect,status,integration/update,disconnect,products/mappings,products/mapping.- ISO-8601 (
c) (e.g."2026-07-16T10:30:00+00:00") — used bystatus/{integrationId}andsystem/status.
Rate limiting & batch limits
Section titled “Rate limiting & batch limits”Rate limiting is enforced at authentication time and keyed by client IP. When the limit is exceeded, the request fails authentication with 401 Unauthorized and this enveloped body:
{ "status": "error", "message": "Rate limit exceeded. Please try again later.", "code": "AUTHENTICATION_FAILED"}The rate-limit-exceeded response (and other authentication failures) carries the current bucket state in response headers:
X-RateLimit-Remaining: 0X-RateLimit-Reset: 1752657600Note that these headers are attached to the 401 authentication-failure response — they are not returned on successful requests. Rate limiting is surfaced as an authentication failure with code AUTHENTICATION_FAILED, not a dedicated rate-limit code or a 429 status.
POST /api/products/push accepts at most 50 products per request. Sending more returns BATCH_SIZE_EXCEEDED.
Error codes
Section titled “Error codes”| Code | HTTP | Meaning | Where |
|---|---|---|---|
AUTHENTICATION_FAILED | 401 | Missing/invalid token, or the IP rate limit was exceeded | any authenticated endpoint |
INVALID_JSON | 400 | Request body is not valid JSON | connect, integration/update, products/push |
MISSING_FIELD | 400 | A required field is missing | connect |
SHOP_NOT_FOUND | 404 | The shop must already exist (app installed) before connecting | connect |
INTEGRATION_EXISTS | 409 | An integration already exists for this shop | connect |
VALIDATION_FAILED | 400 (connect) / 503 (integration/update) | Field validation failed, or credentials could not be validated against MicroPIM | connect, integration/update |
INVALID_CREDENTIALS | 401 | MicroPIM credentials are invalid | connect, integration/update |
CONNECTION_FAILED | 503 | Could not reach MicroPIM to validate credentials | connect |
NO_UPDATES | 400 | No updatable fields were provided | integration/update |
NO_PRODUCTS | 400 | No product data was provided | products/push |
BATCH_SIZE_EXCEEDED | 400 | More than 50 products were submitted | products/push |
MAPPING_NOT_FOUND | 404 | No product mapping exists for the given MicroPIM product id | products/mapping/{id} |
INTERNAL_ERROR | 500 | Unexpected server error | all endpoints |
HTTP status codes
Section titled “HTTP status codes”| Status | Meaning |
|---|---|
| 200 | Success |
| 207 | Partial success (some items in a batch failed) |
| 400 | Bad request (validation, malformed JSON, batch too large) |
| 401 | Missing/invalid token, invalid credentials, or rate limit exceeded |
| 404 | Resource not found |
| 409 | Conflict (integration already exists) |
| 500 | Internal server error |
| 503 | Could not validate credentials against MicroPIM |
Integration lifecycle
Section titled “Integration lifecycle”Connect a storefront
Section titled “Connect a storefront”POST /api/connectPublic — no token required.
Creates a new integration linking a shop to a MicroPIM account. Credentials are validated live against MicroPIM before the integration is created.
Body parameters (all required):
| Parameter | Type | Description |
|---|---|---|
shop_domain | string | Domain of the shop to connect |
micropim_base_url | string | Base URL of the MicroPIM instance |
micropim_api_key | string | MicroPIM API key |
micropim_api_secret | string | MicroPIM API secret |
Example request:
curl -X POST https://app.micropim.net/api/connect \ -H "Content-Type: application/json" \ -d '{ "shop_domain": "example-shop.myshopify.com", "micropim_base_url": "https://demo.micropim.net", "micropim_api_key": "mp_key_123", "micropim_api_secret": "mp_secret_456" }'Example response:
{ "status": "success", "message": "Integration created successfully", "data": { "integration_id": 42, "shop_domain": "example-shop.myshopify.com", "api_token": "a1b2c3d4...", "created_at": "2026-07-16 10:30:00" }}Error codes: INVALID_JSON(400), MISSING_FIELD(400), SHOP_NOT_FOUND(404), INTEGRATION_EXISTS(409), VALIDATION_FAILED(400), INVALID_CREDENTIALS(401), CONNECTION_FAILED(503), INTERNAL_ERROR(500)
Notes:
- The shop must already exist (the app must be installed) or you’ll get
SHOP_NOT_FOUND. - Credentials are live-validated against MicroPIM before the integration is created.
- Save
data.api_token— it’s required for all authenticated endpoints below.
Update integration credentials
Section titled “Update integration credentials”PUT /api/integration/updateRequires token with ROLE_API_ADMIN.
Updates one or more MicroPIM connection fields on an existing integration. Credentials are revalidated against MicroPIM when changed.
Body parameters (optional, at least one required):
| Parameter | Type | Description |
|---|---|---|
micropim_base_url | string | New MicroPIM base URL |
micropim_api_key | string | New MicroPIM API key |
micropim_api_secret | string | New MicroPIM API secret |
Example request:
curl -X PUT https://app.micropim.net/api/integration/update \ -H "Authorization: Bearer a1b2c3d4..." \ -H "Content-Type: application/json" \ -d '{"micropim_api_key": "mp_key_789"}'Example response:
{ "status": "success", "message": "Integration updated successfully", "data": { "integration_id": 42, "updated_at": "2026-07-16 10:45:00" }}Error codes: INVALID_JSON(400), NO_UPDATES(400), INVALID_CREDENTIALS(401), VALIDATION_FAILED(503), INTERNAL_ERROR(500)
Notes:
- Requires an admin-scope (
ROLE_API_ADMIN) token. - At least one field must be provided or you’ll get
NO_UPDATES. - Only the changed connection fields need to be sent.
Disconnect an integration
Section titled “Disconnect an integration”POST /api/disconnectRequires token with ROLE_API_ADMIN. No request body.
Deactivates the integration and revokes all of its API tokens.
Example request:
curl -X POST https://app.micropim.net/api/disconnect \ -H "Authorization: Bearer a1b2c3d4..."Example response:
{ "status": "success", "message": "Integration disconnected successfully", "data": { "integration_id": 42, "status": "inactive", "disconnected_at": "2026-07-16 11:00:00" }}Error codes: INTERNAL_ERROR(500)
Notes:
- After calling this, the token you used is revoked and can no longer authenticate.
- To reconnect, call
POST /api/connectagain to obtain a new token.
Status & monitoring
Section titled “Status & monitoring”Get integration status (authenticated)
Section titled “Get integration status (authenticated)”GET /api/statusRequires a token with any authenticated role.
Returns a detailed health snapshot for the caller’s own integration, including recent sync activity, connectivity checks, and a health score.
Example request:
curl https://app.micropim.net/api/status \ -H "Authorization: Bearer a1b2c3d4..."Example response:
{ "status": "success", "data": { "integration_id": 42, "shop_domain": "example-shop.myshopify.com", "micropim_base_url": "https://demo.micropim.net", "status": "active", "is_active": true, "created_at": "2026-07-16 10:30:00", "last_sync_at": "2026-07-16 12:00:00", "updated_at": "2026-07-16 11:45:00", "product_mapping_stats": { "synced": 120, "pending": 4, "error": 1 }, "recent_syncs": [ { "id": 501, "operation": "products.push", "status": "success", "records_processed": 25, "records_failed": 0, "duration": "1.24s", "started_at": "2026-07-16 12:00:00", "completed_at": "2026-07-16 12:00:01" } ], "micropim_status": { "status": "connected" }, "shopify_status": { "status": "connected", "shop_name": "Example Shop", "shop_id": "gid://shopify/Shop/987654321", "plan": "advanced" }, "active_tokens": 1, "queue_stats": { "pending_messages": 0, "processing_messages": 0, "failed_messages": 0, "note": "Queue stats require message broker integration" }, "health_score": { "score": 96, "status": "excellent", "factors": ["all_syncs_recent", "no_recent_failures"] } }}Error codes: INTERNAL_ERROR(500)
Notes:
product_mapping_statsgroups product mapping counts by sync status; exact keys can vary as new statuses are introduced.micropim_statusandshopify_statusreport{"status": "error", "error": "Unable to connect to MicroPIM"}(or"Unable to connect to Shopify") when the corresponding system can’t be reached.health_score.statusis one of"excellent","good","fair", or"poor".
Get integration status (public)
Section titled “Get integration status (public)”GET /api/status/{integrationId}Public — no token required.
Returns a lightweight, raw (non-enveloped) status object for any integration by ID. Useful for public health checks (e.g. status badges) without exposing a token.
| Path parameter | Type | Description |
|---|---|---|
integrationId | integer | The integration’s numeric ID |
Example request:
curl https://app.micropim.net/api/status/42Example response:
{ "integration_id": 42, "shop_domain": "example-shop.myshopify.com", "is_active": true, "is_connected": true, "last_error": null, "created_at": "2026-07-16T10:30:00+00:00", "last_sync_at": "2026-07-16T12:00:00+00:00", "sync_stats": { "last_24h": { "total_syncs": 8, "successful_syncs": 8, "failed_syncs": 0 }, "product_mappings": { "total": 125, "synced": 120, "pending": 4, "failed": 1 } }, "queue_stats": { "pending_messages": 0, "processing_messages": 0, "failed_messages": 0, "note": "Queue stats require message broker integration" }, "health_score": { "score": 96, "status": "excellent", "factors": ["all_syncs_recent", "no_recent_failures"] }}Error codes: integration not found → {"error": "Integration not found"} (404); check failed → {"error": "Status check failed"} (500)
Notes:
- This response is not wrapped in the
status/dataenvelope used elsewhere on this page. - Timestamps here use ISO-8601 (
c), unlike most other endpoints on this page.
System status
Section titled “System status”GET /api/system/statusPublic — no token required.
Reports overall system operational status, independent of any single integration.
Example request:
curl https://app.micropim.net/api/system/statusExample response:
{ "status": "operational", "timestamp": "2026-07-16T12:05:00+00:00", "stats": { "total_integrations": 340, "active_integrations": 312, "recent_syncs": { "total_syncs_24h": 4820, "successful_syncs_24h": 4790, "failed_syncs_24h": 30 }, "system_health": { "database": "healthy", "php_version": "8.3.9", "memory_usage": "128MB", "memory_peak": "192MB" } }}Error codes: {"status": "error", "timestamp": "...", "error": "System status check failed"} (500)
Notes:
- This response is not wrapped in the
status/dataenvelope;statushere means overall system health, not request success. system_health.databaseis"healthy"or"unhealthy".
Product sync
Section titled “Product sync”Push products
Section titled “Push products”POST /api/products/pushRequires token with ROLE_API_WRITE.
Pushes one or more products from MicroPIM to the connected storefront. Only product data is sent — products, variants, SKUs, prices, stock, images, and categories. Orders and customers are never included, since MicroPIM does not sync them.
Body:
Either a single product object, or a batch:
| Field | Type | Description |
|---|---|---|
id | integer | Required on each product object — the MicroPIM product ID |
products | array | Optional wrapper for pushing a batch; max 50 items |
Example request (batch):
curl -X POST https://app.micropim.net/api/products/push \ -H "Authorization: Bearer a1b2c3d4..." \ -H "Content-Type: application/json" \ -d '{ "products": [ {"id": 1001}, {"id": 1002} ] }'Example response (all succeeded, HTTP 200):
{ "status": "success", "message": "Processed 2 products: 2 successful, 0 failed", "data": { "sync_log_id": 501, "total_products": 2, "successful_count": 2, "failed_count": 0, "results": [ { "status": "success", "message": "Product created", "micropim_product_id": 1001, "shopify_product_id": 555001, "shopify_handle": "product-1001", "method": "create" }, { "status": "success", "message": "Product updated", "micropim_product_id": 1002, "shopify_product_id": 555002, "shopify_handle": "product-1002", "method": "update" } ] }}Example response (partial failure, HTTP 207):
{ "status": "partial", "message": "Processed 2 products: 1 successful, 1 failed", "data": { "sync_log_id": 502, "total_products": 2, "successful_count": 1, "failed_count": 1, "results": [ { "status": "success", "message": "Product updated", "micropim_product_id": 1001, "shopify_product_id": 555001, "shopify_handle": "product-1001", "method": "update" }, { "status": "error", "message": "Validation failed", "micropim_product_id": 1003, "shopify_product_id": null, "validation_errors": ["price is required"] } ] }}Error codes: INVALID_JSON(400), NO_PRODUCTS(400), BATCH_SIZE_EXCEEDED(400), INTERNAL_ERROR(500)
Notes:
- HTTP is
200when every product succeeds (status: "success"), and207when at least one fails (status: "partial"); the partial response has no top-levelcode. - Only product data is pushed — products, variants, SKUs, prices, stock, images, and categories. Never orders or customers.
- Requests with more than 50 products return
BATCH_SIZE_EXCEEDED.
List product mappings
Section titled “List product mappings”GET /api/products/mappingsRequires token with ROLE_API_READ.
Lists the mappings between MicroPIM products and their corresponding storefront products, with pagination.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
limit | integer | Items per page, 1-100 (default: 20) |
offset | integer | Offset for pagination (default: 0) |
status | string | Filter by sync status: pending, synced, error |
Example request:
curl "https://app.micropim.net/api/products/mappings?limit=20&offset=0&status=synced" \ -H "Authorization: Bearer a1b2c3d4..."Example response:
{ "status": "success", "data": { "mappings": [ { "id": 1, "micropim_product_id": 1001, "shopify_product_id": 555001, "shopify_variant_id": 660001, "sync_status": "synced", "sync_error": null, "last_synced_at": "2026-07-16 12:00:00", "created_at": "2026-07-16 10:35:00", "updated_at": "2026-07-16 12:00:00" } ], "pagination": { "total": 125, "limit": 20, "offset": 0, "has_more": true } }}Error codes: INTERNAL_ERROR(500)
Notes:
sync_statusvalues line up with thestatusquery filter:pending,synced,error.- Use
pagination.has_morewithoffset/limitto page through results.
Get a single product mapping
Section titled “Get a single product mapping”GET /api/products/mapping/{microPimProductId}Requires token with ROLE_API_READ.
Returns the mapping and extra metadata for a single MicroPIM product.
| Path parameter | Type | Description |
|---|---|---|
microPimProductId | string | The MicroPIM product ID |
Example request:
curl https://app.micropim.net/api/products/mapping/1001 \ -H "Authorization: Bearer a1b2c3d4..."Example response:
{ "status": "success", "data": { "id": 1, "micropim_product_id": 1001, "shopify_product_id": 555001, "shopify_variant_id": 660001, "sync_status": "synced", "sync_error": null, "last_synced_at": "2026-07-16 12:00:00", "created_at": "2026-07-16 10:35:00", "updated_at": "2026-07-16 12:00:00", "metadata": { "shopify_handle": "product-1001", "shopify_title": "Product 1001", "variant_count": 3, "image_count": 5, "last_push_method": "update" } }}Error codes: MAPPING_NOT_FOUND(404), INTERNAL_ERROR(500)
Notes:
metadatafields describe the storefront-side product and are supplementary — the canonical product data still lives in MicroPIM.- If no mapping exists yet for the given ID, this returns
MAPPING_NOT_FOUND.