API ReferenceEndpointsInstallations

Installations

App-installation endpoints used by marketplace apps via app_inst_* tokens. Write encrypted secrets and manage external-resource mappings tied to a specific installation. The route installationId must match the token; one app cannot read another app’s installation.

List mappings

List mappings for this installation. Paginated; filterable by resourceType, internalId, platformCode, and syncStatus.

GET
/v1/installations/{installationId}/mappings
AuthorizationBearer <token>

App installation token (server-to-server, for marketplace apps). Format: Authorization: Bearer app_inst_xxxxxxxxx. Issued to each AppInstallation row when a merchant installs the app. Scopes are declared by the app manifest; the token cannot escalate beyond them. Used against /api/v1/installations/:installationId/* to read/write mappings and persist OAuth secrets.

In: header

Path Parameters

installationIdstring

Installation ID. Must match the installationId carried by the app_inst_* token.

Query Parameters

resourceType?string

Filter by kind of Brainerce resource.

internalId?string

Filter by Brainerce resource ID.

platformCode?string

Filter by external platform code.

syncStatus?string

Filter by sync status.

Value in"synced" | "pending" | "error" | "stale"
page?integer

Page number, starting at 1.

Default1
Range1 <= value
limit?integer

Page size, 1 to 100. Defaults to 20.

Default20
Range1 <= value <= 100
curl -X GET "https://api.brainerce.com/api/v1/installations/inst_01HXYZ/mappings?resourceType=product&internalId=prod_01HXYZ&platformCode=google-merchant-center&syncStatus=synced&page=1&limit=20"
{
  "data": [
    {
      "id": "clx1a2b3c4d5e6f7g8h9",
      "storeId": "clx1a2b3c4d5e6f7g8h9",
      "installationId": "clx1a2b3c4d5e6f7g8h9",
      "resourceType": "product",
      "internalId": "prod_01HXYZ",
      "externalId": "7891234567890",
      "externalUrl": "https://merchants.google.com/mc/products/7891234567890",
      "platformCode": "google-merchant-center",
      "syncStatus": "synced",
      "lastSyncedAt": "2026-05-20T09:15:00.000Z",
      "lastSyncError": null,
      "metadata": {},
      "createdAt": "2026-05-20T09:15:00.000Z",
      "updatedAt": "2026-05-21T14:02:00.000Z"
    }
  ],
  "meta": {
    "page": 1,
    "limit": 20,
    "total": 137,
    "totalPages": 7
  }
}

{
  "statusCode": 400,
  "code": "VALIDATION_FAILED",
  "message": "name should not be empty, price must be a positive number",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings"
}

{
  "statusCode": 401,
  "code": "UNAUTHORIZED",
  "message": "Invalid or expired credential",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings"
}

{
  "statusCode": 403,
  "code": "INSUFFICIENT_SCOPE",
  "message": "API key does not have the required scope: products:write",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings"
}

{
  "statusCode": 429,
  "code": "RATE_LIMITED",
  "message": "Too many requests",
  "details": {
    "retryAfterSeconds": 12
  },
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings"
}

Create a mapping

Register that a Brainerce resource (product, order, customer, …) corresponds to a resource on the app’s external platform. The mapping is keyed by (installationId, resourceType, internalId, platformCode). Duplicates are rejected; use PUT /upsert instead.

POST
/v1/installations/{installationId}/mappings
AuthorizationBearer <token>

App installation token (server-to-server, for marketplace apps). Format: Authorization: Bearer app_inst_xxxxxxxxx. Issued to each AppInstallation row when a merchant installs the app. Scopes are declared by the app manifest; the token cannot escalate beyond them. Used against /api/v1/installations/:installationId/* to read/write mappings and persist OAuth secrets.

In: header

Path Parameters

installationIdstring

Installation ID. Must match the installationId carried by the app_inst_* token.

resourceTypestring

Type of Brainerce resource being mapped.

Value in"product" | "variant" | "order" | "customer" | "category" | "brand" | "tag" | "coupon"
internalIdstring

Internal Brainerce resource ID (e.g. product.id).

externalIdstring

External resource ID on the app’s platform.

externalUrl?string

Optional canonical URL to the resource on the external platform, surfaced in the dashboard UI.

platformCodestring

Platform code identifying the external platform (matches the App.platformCode field on the installed app).

syncStatus?string

Initial sync status. Defaults to synced.

Default"synced"
Value in"synced" | "pending" | "error" | "stale"
metadata?object

Free-form metadata JSON holding platform-specific data, for example the platform handle or status. Stored as-is and never interpreted by Brainerce.

curl -X POST "https://api.brainerce.com/api/v1/installations/inst_01HXYZ/mappings" \  -H "Content-Type: application/json" \  -d '{    "resourceType": "product",    "internalId": "prod_01HXYZ",    "externalId": "7891234567890",    "platformCode": "google-merchant-center"  }'
{
  "id": "clx1a2b3c4d5e6f7g8h9",
  "storeId": "clx1a2b3c4d5e6f7g8h9",
  "installationId": "clx1a2b3c4d5e6f7g8h9",
  "resourceType": "product",
  "internalId": "prod_01HXYZ",
  "externalId": "7891234567890",
  "externalUrl": "https://merchants.google.com/mc/products/7891234567890",
  "platformCode": "google-merchant-center",
  "syncStatus": "synced",
  "lastSyncedAt": "2026-05-20T09:15:00.000Z",
  "lastSyncError": null,
  "metadata": {},
  "createdAt": "2026-05-20T09:15:00.000Z",
  "updatedAt": "2026-05-21T14:02:00.000Z"
}

{
  "statusCode": 400,
  "code": "VALIDATION_FAILED",
  "message": "name should not be empty, price must be a positive number",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings"
}

{
  "statusCode": 401,
  "code": "UNAUTHORIZED",
  "message": "Invalid or expired credential",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings"
}

{
  "statusCode": 403,
  "code": "INSUFFICIENT_SCOPE",
  "message": "API key does not have the required scope: products:write",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings"
}

{
  "statusCode": 409,
  "code": "CONFLICT",
  "message": "The request conflicts with the current state of the resource",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings"
}

{
  "statusCode": 429,
  "code": "RATE_LIMITED",
  "message": "Too many requests",
  "details": {
    "retryAfterSeconds": 12
  },
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings"
}

Get a mapping

Return one mapping by ID. 404 if the mapping does not belong to this installation.

GET
/v1/installations/{installationId}/mappings/{mappingId}
AuthorizationBearer <token>

App installation token (server-to-server, for marketplace apps). Format: Authorization: Bearer app_inst_xxxxxxxxx. Issued to each AppInstallation row when a merchant installs the app. Scopes are declared by the app manifest; the token cannot escalate beyond them. Used against /api/v1/installations/:installationId/* to read/write mappings and persist OAuth secrets.

In: header

Path Parameters

installationIdstring

Installation ID. Must match the installationId carried by the app_inst_* token.

mappingIdstring

Mapping ID.

curl -X GET "https://api.brainerce.com/api/v1/installations/inst_01HXYZ/mappings/map_01HXYZ"
{
  "id": "clx1a2b3c4d5e6f7g8h9",
  "storeId": "clx1a2b3c4d5e6f7g8h9",
  "installationId": "clx1a2b3c4d5e6f7g8h9",
  "resourceType": "product",
  "internalId": "prod_01HXYZ",
  "externalId": "7891234567890",
  "externalUrl": "https://merchants.google.com/mc/products/7891234567890",
  "platformCode": "google-merchant-center",
  "syncStatus": "synced",
  "lastSyncedAt": "2026-05-20T09:15:00.000Z",
  "lastSyncError": null,
  "metadata": {},
  "createdAt": "2026-05-20T09:15:00.000Z",
  "updatedAt": "2026-05-21T14:02:00.000Z"
}

{
  "statusCode": 401,
  "code": "UNAUTHORIZED",
  "message": "Invalid or expired credential",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings/{mappingId}"
}

{
  "statusCode": 403,
  "code": "INSUFFICIENT_SCOPE",
  "message": "API key does not have the required scope: products:write",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings/{mappingId}"
}

{
  "statusCode": 404,
  "code": "RESOURCE_NOT_FOUND",
  "message": "Resource not found",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings/{mappingId}"
}

{
  "statusCode": 429,
  "code": "RATE_LIMITED",
  "message": "Too many requests",
  "details": {
    "retryAfterSeconds": 12
  },
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings"
}

Update a mapping

Partial update: only the fields you provide are written. Useful for transitioning syncStatus and recording lastSyncedAt / lastSyncError.

PATCH
/v1/installations/{installationId}/mappings/{mappingId}
AuthorizationBearer <token>

App installation token (server-to-server, for marketplace apps). Format: Authorization: Bearer app_inst_xxxxxxxxx. Issued to each AppInstallation row when a merchant installs the app. Scopes are declared by the app manifest; the token cannot escalate beyond them. Used against /api/v1/installations/:installationId/* to read/write mappings and persist OAuth secrets.

In: header

Path Parameters

installationIdstring

Installation ID. Must match the installationId carried by the app_inst_* token.

mappingIdstring

Mapping ID.

externalId?string

Updated external resource ID.

externalUrl?string

Updated URL to the resource on the external platform.

syncStatus?string

Updated sync status.

Value in"synced" | "pending" | "error" | "stale"
lastSyncedAt?string

Timestamp of last successful sync (ISO 8601).

lastSyncError?string | null

Last sync error message. Pass null to clear the error.

metadata?object

Free-form metadata JSON holding platform-specific data. Replaces the stored value. Never interpreted by Brainerce.

curl -X PATCH "https://api.brainerce.com/api/v1/installations/inst_01HXYZ/mappings/map_01HXYZ" \  -H "Content-Type: application/json" \  -d '{}'
{
  "id": "clx1a2b3c4d5e6f7g8h9",
  "storeId": "clx1a2b3c4d5e6f7g8h9",
  "installationId": "clx1a2b3c4d5e6f7g8h9",
  "resourceType": "product",
  "internalId": "prod_01HXYZ",
  "externalId": "7891234567890",
  "externalUrl": "https://merchants.google.com/mc/products/7891234567890",
  "platformCode": "google-merchant-center",
  "syncStatus": "synced",
  "lastSyncedAt": "2026-05-20T09:15:00.000Z",
  "lastSyncError": null,
  "metadata": {},
  "createdAt": "2026-05-20T09:15:00.000Z",
  "updatedAt": "2026-05-21T14:02:00.000Z"
}

{
  "statusCode": 400,
  "code": "VALIDATION_FAILED",
  "message": "name should not be empty, price must be a positive number",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings/{mappingId}"
}

{
  "statusCode": 401,
  "code": "UNAUTHORIZED",
  "message": "Invalid or expired credential",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings/{mappingId}"
}

{
  "statusCode": 403,
  "code": "INSUFFICIENT_SCOPE",
  "message": "API key does not have the required scope: products:write",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings/{mappingId}"
}

{
  "statusCode": 404,
  "code": "RESOURCE_NOT_FOUND",
  "message": "Resource not found",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings/{mappingId}"
}

{
  "statusCode": 409,
  "code": "CONFLICT",
  "message": "The request conflicts with the current state of the resource",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings/{mappingId}"
}

{
  "statusCode": 429,
  "code": "RATE_LIMITED",
  "message": "Too many requests",
  "details": {
    "retryAfterSeconds": 12
  },
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings"
}

Delete a mapping

Remove a mapping. The Brainerce resource itself is untouched: this only unlinks the external counterpart.

DELETE
/v1/installations/{installationId}/mappings/{mappingId}
AuthorizationBearer <token>

App installation token (server-to-server, for marketplace apps). Format: Authorization: Bearer app_inst_xxxxxxxxx. Issued to each AppInstallation row when a merchant installs the app. Scopes are declared by the app manifest; the token cannot escalate beyond them. Used against /api/v1/installations/:installationId/* to read/write mappings and persist OAuth secrets.

In: header

Path Parameters

installationIdstring

Installation ID. Must match the installationId carried by the app_inst_* token.

mappingIdstring

Mapping ID.

curl -X DELETE "https://api.brainerce.com/api/v1/installations/inst_01HXYZ/mappings/map_01HXYZ"
Empty

{
  "statusCode": 401,
  "code": "UNAUTHORIZED",
  "message": "Invalid or expired credential",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings/{mappingId}"
}

{
  "statusCode": 403,
  "code": "INSUFFICIENT_SCOPE",
  "message": "API key does not have the required scope: products:write",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings/{mappingId}"
}

{
  "statusCode": 404,
  "code": "RESOURCE_NOT_FOUND",
  "message": "Resource not found",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings/{mappingId}"
}

{
  "statusCode": 429,
  "code": "RATE_LIMITED",
  "message": "Too many requests",
  "details": {
    "retryAfterSeconds": 12
  },
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings"
}

Upsert a mapping

Create the mapping if it does not exist, otherwise update the existing row. Uniqueness key: (installationId, resourceType, internalId, platformCode). Idempotent, and recommended for sync loops.

PUT
/v1/installations/{installationId}/mappings/upsert
AuthorizationBearer <token>

App installation token (server-to-server, for marketplace apps). Format: Authorization: Bearer app_inst_xxxxxxxxx. Issued to each AppInstallation row when a merchant installs the app. Scopes are declared by the app manifest; the token cannot escalate beyond them. Used against /api/v1/installations/:installationId/* to read/write mappings and persist OAuth secrets.

In: header

Path Parameters

installationIdstring

Installation ID. Must match the installationId carried by the app_inst_* token.

resourceTypestring

Type of Brainerce resource being mapped.

Value in"product" | "variant" | "order" | "customer" | "category" | "brand" | "tag" | "coupon"
internalIdstring

Internal Brainerce resource ID (e.g. product.id).

externalIdstring

External resource ID on the app’s platform.

externalUrl?string

Optional canonical URL to the resource on the external platform, surfaced in the dashboard UI.

platformCodestring

Platform code identifying the external platform (matches the App.platformCode field on the installed app).

syncStatus?string

Initial sync status. Defaults to synced.

Default"synced"
Value in"synced" | "pending" | "error" | "stale"
metadata?object

Free-form metadata JSON holding platform-specific data, for example the platform handle or status. Stored as-is and never interpreted by Brainerce.

curl -X PUT "https://api.brainerce.com/api/v1/installations/inst_01HXYZ/mappings/upsert" \  -H "Content-Type: application/json" \  -d '{    "resourceType": "product",    "internalId": "prod_01HXYZ",    "externalId": "7891234567890",    "platformCode": "google-merchant-center"  }'
{
  "id": "clx1a2b3c4d5e6f7g8h9",
  "storeId": "clx1a2b3c4d5e6f7g8h9",
  "installationId": "clx1a2b3c4d5e6f7g8h9",
  "resourceType": "product",
  "internalId": "prod_01HXYZ",
  "externalId": "7891234567890",
  "externalUrl": "https://merchants.google.com/mc/products/7891234567890",
  "platformCode": "google-merchant-center",
  "syncStatus": "synced",
  "lastSyncedAt": "2026-05-20T09:15:00.000Z",
  "lastSyncError": null,
  "metadata": {},
  "createdAt": "2026-05-20T09:15:00.000Z",
  "updatedAt": "2026-05-21T14:02:00.000Z"
}

{
  "statusCode": 400,
  "code": "VALIDATION_FAILED",
  "message": "name should not be empty, price must be a positive number",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings/upsert"
}

{
  "statusCode": 401,
  "code": "UNAUTHORIZED",
  "message": "Invalid or expired credential",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings/{mappingId}"
}

{
  "statusCode": 403,
  "code": "INSUFFICIENT_SCOPE",
  "message": "API key does not have the required scope: products:write",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings/{mappingId}"
}

{
  "statusCode": 429,
  "code": "RATE_LIMITED",
  "message": "Too many requests",
  "details": {
    "retryAfterSeconds": 12
  },
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/mappings"
}

Write installation secrets

Merge keys into the encrypted secrets bag attached to an installation. Used by marketplace apps to persist OAuth tokens, signing secrets, or provider-specific credentials after completing their setup flow. Keys you send overwrite the stored value; keys you do not send are kept (a refreshed access token does not remove the stored refresh token). Send a key with the value null to delete it. The merged bag is capped at 64 KB. A write that races another write to the same installation answers 409; retry it. Allowed while the installation is PENDING (OAuth setup) or INSTALLED. Secrets are encrypted at rest with AES-256-GCM. Requires the config:write scope.

PUT
/v1/installations/{installationId}/secrets
AuthorizationBearer <token>

App installation token (server-to-server, for marketplace apps). Format: Authorization: Bearer app_inst_xxxxxxxxx. Issued to each AppInstallation row when a merchant installs the app. Scopes are declared by the app manifest; the token cannot escalate beyond them. Used against /api/v1/installations/:installationId/* to read/write mappings and persist OAuth secrets.

In: header

Path Parameters

installationIdstring

Installation ID. Must match the installationId carried by the app_inst_* token.

secretsobject

Key/value pairs to encrypt and store on the installation. They are MERGED over the stored secrets: keys you send overwrite the stored value, keys you do not send are kept. Send a key with the value null to delete it. Must be a non-empty object.

curl -X PUT "https://api.brainerce.com/api/v1/installations/inst_01HXYZ/secrets" \  -H "Content-Type: application/json" \  -d '{    "secrets": {      "access_token": "shpat_xxx",      "refresh_token": "rt_yyy"    }  }'
{
  "success": true
}

{
  "statusCode": 400,
  "code": "VALIDATION_FAILED",
  "message": "name should not be empty, price must be a positive number",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/secrets"
}

{
  "statusCode": 401,
  "code": "UNAUTHORIZED",
  "message": "Invalid or expired credential",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/secrets"
}

{
  "statusCode": 403,
  "code": "INSUFFICIENT_SCOPE",
  "message": "API key does not have the required scope: products:write",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/secrets"
}

{
  "statusCode": 404,
  "code": "RESOURCE_NOT_FOUND",
  "message": "Resource not found",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/secrets"
}

{
  "statusCode": 409,
  "code": "CONFLICT",
  "message": "The request conflicts with the current state of the resource",
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/secrets"
}

{
  "statusCode": 429,
  "code": "RATE_LIMITED",
  "message": "Too many requests",
  "details": {
    "retryAfterSeconds": 12
  },
  "timestamp": "2026-08-23T10:15:00.000Z",
  "path": "/api/v1/installations/{installationId}/secrets"
}