Measura API documentation · v1

Kit recipes

Manage recipes linked to existing Shopify products and variants.

Access and identifiers

These endpoints require a public API key with Public API access and an active Kit Builder add-on with an available tier. Kit IDs are 24 hexadecimal characters. Shopify product and variant IDs are positive legacy numeric ID strings, rather than GraphQL GIDs.

Recipe writes and stock:

Saving a recipe links existing Shopify variants and validates their eligibility and measurement conversions. It does not assemble kits or move inventory. Use Kit assemblies to change stock.
Code example
GET /api/v1/kits

Headers:
  Authorization: Bearer <api-key>

Query parameters

Scroll horizontally to see all columns.

ParameterTypeDescription
limitintegerOptional. 1–100 recipes; default 50.
cursorstringOptional. Use meta.nextCursor from the previous page. Recipe cursors are kit IDs.

Response example (200 success)

Code example
{
  "success": true,
  "data": [
    {
      "id": "507f1f77bcf86cd799439011",
      "title": "Coffee gift box",
      "description": "Two measured portions",
      "productId": "100",
      "variantId": "101",
      "components": [
        {
          "productId": "200",
          "variantId": "201",
          "quantity": 2,
          "measurement": {
            "value": 250,
            "unit": "g",
            "type": "weight"
          }
        }
      ],
      "revision": "2026-10-17T08:00:00.000Z",
      "createdAt": "2026-10-17T08:00:00.000Z",
      "updatedAt": "2026-10-17T08:00:00.000Z"
    }
  ],
  "error": null,
  "meta": {
    "hasMore": false,
    "nextCursor": null
  }
}

Note

Recipes are ordered by kit ID ascending. This forward pagination has no prevCursor. All kit reads and writes return Cache-Control: no-store.

Code example
GET /api/v1/kits/{id}

Headers:
  Authorization: Bearer <api-key>

Path parameters

Scroll horizontally to see all columns.

ParameterTypeDescription
idstringRequired. Kit ID, 24 hexadecimal characters.

Response example (200 success)

Code example
{
  "success": true,
  "data": {
    "id": "507f1f77bcf86cd799439011",
    "title": "Coffee gift box",
    "description": "Two measured portions",
    "productId": "100",
    "variantId": "101",
    "components": [
      {
        "productId": "200",
        "variantId": "201",
        "quantity": 2,
        "measurement": {
          "value": 250,
          "unit": "g",
          "type": "weight"
        }
      }
    ],
    "revision": "2026-10-17T08:00:00.000Z",
    "createdAt": "2026-10-17T08:00:00.000Z",
    "updatedAt": "2026-10-17T08:00:00.000Z"
  },
  "error": null
}

Response fields

Scroll horizontally to see all columns.

FieldTypeDescription
data.idstringKit recipe ID.
data.title / descriptionstringRecipe title and optional description. Description may be omitted.
data.productId / variantIdstringExisting Shopify product and output variant linked to the kit.
data.componentsarrayComponent definitions, including quantity and optional measurement.
data.revisionstringExact ISO timestamp to pass as expectedRevision for PATCH or DELETE.
data.createdAt / updatedAtstringISO timestamps for creation and last update.
Code example
POST /api/v1/kits

Headers:
  Authorization: Bearer <api-key>
  Content-Type: application/json
  Idempotency-Key: <unique-operation-key>

Request body

Code example
{
  "title": "Coffee gift box",
  "description": "Two measured portions",
  "productId": "100",
  "variantId": "101",
  "components": [
    {
      "productId": "200",
      "variantId": "201",
      "quantity": 2,
      "measurement": {
        "value": 250,
        "unit": "g",
        "type": "weight"
      }
    }
  ]
}

Response example (200 success)

Code example
{
  "success": true,
  "data": {
    "kit": {
      "id": "507f1f77bcf86cd799439011",
      "title": "Coffee gift box",
      "description": "Two measured portions",
      "productId": "100",
      "variantId": "101",
      "components": [
        {
          "productId": "200",
          "variantId": "201",
          "quantity": 2,
          "measurement": {
            "value": 250,
            "unit": "g",
            "type": "weight"
          }
        }
      ],
      "revision": "2026-10-17T08:00:00.000Z",
      "createdAt": "2026-10-17T08:00:00.000Z",
      "updatedAt": "2026-10-17T08:00:00.000Z"
    },
    "operationId": "7f7831f2-2675-4f5c-ae59-4c2d04095a60",
    "operationStatus": "completed"
  },
  "error": null
}

Note

A successful create returns HTTP 200. Creation consumes the kit allowance of the active add-on tier; an exhausted allowance returns kit_limit_reached (409).

Recipe fields

Scroll horizontally to see all columns.

FieldTypeDescription
titlestringRequired on create. Nonblank, at most 255 characters; surrounding whitespace is trimmed.
descriptionstringOptional, at most 5,000 characters. Use an empty string to clear it.
productId / variantIdstringRequired on create. Existing product and output variant IDs; the variant must belong to the product.
componentsarrayRequired on create. 1–50 component objects. PATCH replaces this entire array when supplied.
components[].productId / variantIdstringRequired existing Shopify IDs. Each variant must belong to its product and cannot be the kit output variant.
components[].quantityintegerRequired. 1–1,000,000. Without measurement, consumes this many stock units per kit.
components[].measurementobjectOptional. When supplied, each quantity consumes this measured amount; the server converts it to the variant’s configured stock units.
measurement.valuenumberRequired within measurement. Finite, greater than zero and at most 1,000,000,000.
measurement.typestringRequired within measurement. weight, length, volume, area or time; must match the component’s measurement configuration.
measurement.unitstringRequired within measurement. A known unit label or name for the stated type. Unknown or incompatible units are rejected.

Unknown fields are rejected at every validated object level. Numeric strings are not accepted for quantity or measurement.value. Measured variants must be eligible under the shop’s configuration and plan; the API also validates conversion and supported numeric limits before saving.

Code example
PATCH /api/v1/kits/{id}

Headers:
  Authorization: Bearer <api-key>
  Content-Type: application/json
  Idempotency-Key: <unique-operation-key>

Path parameters

Scroll horizontally to see all columns.

ParameterTypeDescription
idstringRequired. Kit ID.

Request body

Code example
{
  "expectedRevision": "2026-10-17T08:00:00.000Z",
  "title": "Coffee sampler box"
}

Note

Pass the exact current revision from GET and at least one recipe field to update. Omitted fields keep their current values. The response has the same data.kit, operationId and operationStatus shape as create, with the updated recipe. A concurrent change returns revision_conflict (409); read the latest recipe before preparing a new operation.

Code example
DELETE /api/v1/kits/{id}

Headers:
  Authorization: Bearer <api-key>
  Content-Type: application/json
  Idempotency-Key: <unique-operation-key>

Path parameters

Scroll horizontally to see all columns.

ParameterTypeDescription
idstringRequired. Kit ID.

Request body

Code example
{
  "expectedRevision": "2026-10-17T08:00:00.000Z"
}

Response example (200 success)

Code example
{
  "success": true,
  "data": {
    "deleted": true,
    "kitId": "507f1f77bcf86cd799439011",
    "operationId": "7f7831f2-2675-4f5c-ae59-4c2d04095a60",
    "operationStatus": "completed"
  },
  "error": null
}

Note

The body accepts only expectedRevision. Deletion removes the recipe while preserving Shopify products, inventory and production history. Historical public assemblies retain the snapshots needed for disassembly.

Retries and errors

Every write requires an Idempotency-Key of 1–255 characters. Receipts are retained permanently for this shop. Retry the same operation with the same key; a completed replay returns Idempotency-Replayed: true. Recipe writes and assemblies share the shop’s kit write scope, so another pending operation can temporarily block a write.

If the result is uncertain, retrieve the operation using the operationId in the response or error details. Follow the write safety guide before starting another write.

Scroll horizontally to see all columns.

StatusDescription
400Malformed JSON or missing/invalid Idempotency-Key.
401 / 403Invalid credentials, unavailable Public API access, or inactive/unavailable Kit Builder add-on tier.
404Kit not found in the authenticated shop.
405Unsupported method.
409revision_conflict, kit_limit_reached, idempotency_key_reused, operation_in_progress, resource_in_progress or operation_requires_review.
422Invalid fields/IDs/revisions, variant_product_mismatch, variant_not_eligible or invalid measurement/conversion configuration.
500Unexpected server or upstream failure. Preserve the key when retrying an uncertain request.