avut.io
AuthenticationEndpointsErrorsMCP docsOpenAPI JSON

Avut-pim API

Build product data integrations without the guesswork.

Use tenant-scoped API keys to connect products, media, structures, feeds, imports, and search to the systems that run your commerce operations.

106
documented operations
63
public paths
2
auth methods

API Reference

Getting StartedAuthenticationVersioningDelta SyncToolsIdentifiersEndpointsErrorsRate Limits

Search method, path, summary, group, or scope.

Use for product sync, enrichment, product detail pages, and operational product updates.

14 read21 write

Core products

Delta sync and changes

Lifecycle

Attributes

Relations

Packaging

Media

Collections

Getting Started

Create an API key in Avut-pim under Settings, then call public endpoints from your integration. API keys are tenant-scoped and permission-scoped.

Create a sandbox key
Choose read or write scope
Call documented endpoints

Authentication

Send your tenant-scoped API key with every public API request. Bearer auth is recommended, while custom API key headers are supported for systems that require them.

Sandbox keys

Use a sandbox API key while building an integration. Sandbox keys call the same /api/v1 endpoints, but authenticate into an isolated sandbox tenant so test imports, updates, and deletes do not touch production data.

Bearer auth

Recommended for most integrations. Add this header to every API request.

Authorization: Bearer <API_KEY>

Header auth

Useful for systems that prefer custom API key headers. Use either this or Bearer auth, not both.

x-api-key: <API_KEY>

Versioning

Public endpoints use the /api/v1 prefix. Version 1 is the stable integration contract for customer-facing API clients.

Stable path

Use /api/v1 in production integrations. Unversioned app routes are not part of the public API contract.

Breaking changes

Breaking changes will use a future version instead of changing existing v1 behavior.

Non-breaking additions

New optional fields, enum values, and endpoints may be added to v1. Clients should ignore unknown fields.

Deprecation policy

Deprecated public API behavior keeps a minimum 90-day removal window. Notices must include the replacement endpoint or behavior, timeline, and migration steps.

/api/v1 is the compatibility version. The date in the OpenAPI document is the published contract revision within v1.

A breaking change moves to a new path such as /api/v2. Avut publishes migration steps and runs both versions during the announced deprecation window.

Delta Sync Quick Recipe

Use the changed-products endpoint as a lightweight index before fetching product details.

1

Call changes

Send since with your last stored watermark.

2

Page results

Keep the same since/until and follow nextCursor until null.

3

Fetch details

Fetch the full product or product change events only when needed.

4

Store watermark

After all pages succeed, store the returned until value.

GET /api/v1/products/changes?since=2026-05-15T08:00:00Z&include_fields=true&limit=100

Tools

Use the OpenAPI specification for code generation and the Postman collection for manual testing.

Authentication header

Set your tenant API key as the apiKey variable in Postman, or send this header from your integration:

Authorization: Bearer <API_KEY>

OpenAPI JSON

Machine-readable API specification for generated clients and contract checks.

Open specification

Postman collection

Download the generated collection with public paths, documented query parameters, and authentication configured. Add write payloads from the endpoint docs before sending POST or PATCH requests.

Download collection

Identifiers, Codes, and Keys

Public responses include Avut system ids and business-readable identifiers. Use each for the job it is best suited for.

Use id for API links

Use id when calling detail, update, relation, packaging, or other resource-specific endpoints.

Use code/key for mapping

Use stable business identifiers such as structure code, attribute key, and value-list key for integration mapping rules.

Use SKU for product lookup

Use sku for product matching with ERP, ecommerce, and import/export workflows. Keep id after the first lookup.

{
  "id": "7f4319e6-d3e4-4531-a619-8b9507a8a1c0",
  "sku": "SAMPLE-SKU-001",
  "brand": {
    "id": "b2626dd1-3ad7-4a90-8986-ed881aa826e0",
    "name": "Avut Sample Brand",
    "code": "avut-sample-brand"
  },
  "attributes": {
    "sample_color": "Black"
  }
}

Endpoints

Public API Reference

These are the documented customer-facing endpoints. Internal, operator, user, tenant, settings, and Shopify-internal routes are intentionally excluded.

Product request and core response fields use snake_case. Some established feed, media, and configuration payloads retain documented camelCase fields for compatibility; use the exact field names shown for each endpoint.

Products

Create, read, update, and connect product records, attributes, relations, and packaging data.

Use for product sync, enrichment, product detail pages, and operational product updates.

read

14

write

21

get/api/v1/products

List products

List products in the products API.

read scope

Group

Core products

Auth

Bearer or x-api-key

Base URL

https://api.avut.io

Path parameters

This endpoint has no path parameters.

Query parameters

FieldTypeRequiredDescription
limitintegerNoMaximum records to return. Defaults to 50 and is capped at 100 without expansions or 25 when expand is used.
cursorstringNoPagination cursor returned as nextCursor from the previous page.
searchstringNoCase-insensitive product search across supported product identifiers and text fields.
filtersstringNoJSON-encoded advanced product filters using the same filter clauses supported by the product list.
includeArchivedbooleanNoLegacy compatibility flag that includes archived rows. Prefer status=archived or status=all for new integrations.
skustringNoOptional comma-separated list of exact SKUs to return. The list is capped at 100 SKUs.
statusstringNoProduct status filter. Defaults to active.
updated_sincestringNoReturn products updated after this ISO 8601 timestamp.
updated_beforestringNoReturn products updated at or before this ISO 8601 timestamp.
include_i18nbooleanNoSet true to include localized/translatable values in the response.
expandstringNoComma-separated linked data to include: media, relations, collections, bundle_components, assortment_items, variants, packaging, or all.

Request fields

This endpoint does not require a JSON request body.

Success responses

CodeDescription
200Resource returned.

Response fields

FieldTypeReturnedDescription
dataarray<object>AlwaysProduct records. Each item can include the product fields below.
nextCursorstring|nullOptionalCursor for the next page, or null when there are no more results.
limitintegerAlwaysMaximum number of records returned in the page.

Credentials

Authorization: Bearer <API_KEY>
x-api-key: <API_KEY>

URL

GET https://api.avut.io/api/v1/products

Example

cURL

curl -sS "https://api.avut.io/api/v1/products?limit=50" \
  -H "Authorization: Bearer $AVUT_API_KEY"

Response example

{
  "data": [
    {
      "id": "prd_01J9Z7QH8V8C2P2K7A6X9M4D3E",
      "sku": "JACKET-NORDIC-001",
      "name": "Nordic performance jacket",
      "description": "Lightweight shell jacket for changing weather.",
      "status": {
        "id": "status_01J9Z7QH8V8C2P2K7A6X9M4D3E",
        "name": "Active",
        "code": "active"
      },
      "product_kind": "standard",
      "brand": {
        "id": "brand_01J9Z7QH8V8C2P2K7A6X9M4D3E",
        "name": "Avut Sample Brand",
        "code": "avut-sample-brand"
      },
      "supplier": {
        "id": "sup_01J9Z7QH8V8C2P2K7A6X9M4D3E",
        "name": "Avut Sample Supplier",
        "code": "avut-sample-supplier",
        "supplier_code": "SUP-100"
      },
      "product_group": {
        "id": "grp_01J9Z7QH8V8C2P2K7A6X9M4D3E",
        "name": "Jackets",
        "code": "jackets"
      },
      "packaging": {
        "roles": [
          {
            "role": {
              "id": "pkg_role_01J9Z7QH8V8C2P2K7A6X9M4D3E",
              "code": "consumer_unit",
              "name": "Consumer unit",
              "semantic": "consumer_unit",
              "isBaseLevel": true
            },
            "colli": {
              "index": 0,
              "label": "Colli 1",
              "description": null
            },
            "type": {
              "id": "pkg_type_01J9Z7QH8V8C2P2K7A6X9M4D3E",
              "name": "Polybag",
              "code": "polybag"
            },
            "gtin": "1234567890123",
            "additionalGtins": [],
            "quantityToConsumerUnit": "1",
            "dimensions": {
              "length": "45",
              "width": "35",
              "height": "8",
              "unit": "cm"
            },
            "volume": {
              "value": "12600",
              "unit": "cm3",
              "source": "derived"
            },
            "weights": {
              "net": "0.9",
              "gross": "1",
              "unit": "kg"
            }
          },
          {
            "role": {
              "id": "pkg_role_01J9Z7QH8V8C2P2K7A6X9M4D3F",
              "code": "master_carton",
              "name": "Master carton",
              "semantic": "master_carton",
              "isBaseLevel": false
            },
            "colli": {
              "index": 0,
              "label": "Colli 1",
              "description": null
            },
            "type": {
              "id": "pkg_type_01J9Z7QH8V8C2P2K7A6X9M4D3F",
              "name": "Brown box",
              "code": "brown_box"
            },
            "gtin": null,
            "additionalGtins": [],
            "quantityToConsumerUnit": "12",
            "dimensions": {
              "length": "60",
              "width": "40",
              "height": "30",
              "unit": "cm"
            },
            "volume": {
              "value": "72",
              "unit": "dm3",
              "source": "derived"
            },
            "weights": {
              "net": null,
              "gross": "8.4",
              "unit": "kg"
            }
          }
        ]
      },
      "eu_taric_code": "6201401000",
      "no_tariff_code": "62014000",
      "eu_antidumping_declarations": [],
      "tariff_signals": {
        "high_duty": {
          "status": "none",
          "source": "no",
          "code": "62014000",
          "duty": null,
          "threshold": 10
        },
        "anti_dumping": {
          "status": "none",
          "source": "taric",
          "code": "6201401000",
          "requires_declaration": false,
          "declarations_count": 0,
          "additional_codes": []
        }
      },
      "categories": [
        {
          "id": "cat_01J9Z7QH8V8C2P2K7A6X9M4D3E",
          "name": "Outerwear",
          "code": "outerwear"
        }
      ],
      "variant_model": {
        "id": "variant_model_01J9Z7QH8V8C2P2K7A6X9M4D3E",
        "name": "Color + Size",
        "code": "color_size"
      },
      "variant_parent": null,
      "variant_options": [
        {
          "dimension": {
            "id": "dim_01J9Z7QH8V8C2P2K7A6X9M4D3E",
            "name": "Size",
            "type": "size"
          },
          "option": {
            "id": "opt_01J9Z7QH8V8C2P2K7A6X9M4D3E",
            "name": "M"
          }
        }
      ],
      "archived_at": null,
      "updated_at": "2026-05-14T12:30:00.000Z",
      "gtin": "1234567890123",
      "product_template": {
        "id": "tpl_01J9Z7QH8V8C2P2K7A6X9M4D3E",
        "name": "Apparel"
      },
      "attributes": {
        "sample_color": "Black",
        "sample_material": "Recycled polyester"
      },
      "attribute_count": 2,
      "mediaSummary": {
        "count": 3,
        "primaryUrl": "https://cdn.example.com/products/jacket-original.jpg",
        "primaryThumbUrl": "https://cdn.example.com/products/jacket-thumb.jpg"
      },
      "mediaStatus": {
        "level": "ok",
        "issues": [],
        "mediaCount": 3,
        "primaryWidth": 1600,
        "primaryHeight": 2000,
        "rules": {
          "minPrimaryWidth": 800,
          "minPrimaryHeight": 800,
          "minImageCount": null
        }
      },
      "variantMediaCount": 0
    }
  ],
  "nextCursor": null,
  "limit": 50
}

Errors

Error responses use JSON with an error message. Rate-limited requests may include retry metadata.

{
  "error": "Unauthorized"
}
{
  "error": "Rate limit exceeded.",
  "code": "rate_limited",
  "retryAt": "2026-05-03T12:30:00.000Z"
}
StatusMeaningWhat to check
400Invalid requestPayload, query parameter, cursor, or validation errors.
401UnauthorizedMissing, malformed, or invalid API key.
402Quota exceededUpgrade the plan or wait until resetAt before retrying.
403ForbiddenAPI key is valid but does not have the required scope.
404Not foundResource id, SKU lookup, or path parameter does not match a resource.
409ConflictDuplicate SKU/key/code, relation conflict, or incompatible state.
429Rate limitedWait until retryAt, then retry with backoff.

Rate Limits

API key traffic uses fixed-window throttling. A request can be limited by the API key, by the tenant, or by the same API key repeatedly calling the same endpoint. Long-running work should be queued through jobs, imports, or feed runs instead of retried in tight loops.

Per API key

120 requests / 60 seconds

Protects one key from runaway clients.

Per tenant

600 requests / 60 seconds

Protects total tenant traffic across keys.

Per key + endpoint

60 requests / 60 seconds

Protects hot endpoints during sync loops.

How to handle 429 responses

When the limit is reached, Avut-pim returns 429 with code: RATE_LIMITED and a retryAt ISO timestamp. Clients should pause until that time, then retry with exponential backoff and jitter for repeated failures. Avoid tight retry loops and keep long-running syncs paginated.

API boundaries

API keys access the customer-facing endpoints documented here.

Users, tenant administration, settings, operator tools, and connector setup are managed in the Avut PIM app.

Large imports, feed generation, AI work, and media preparation should use queued jobs and status endpoints.

Server-to-server only

Browser CORS access is not supported. Keep API keys in a backend, worker, or secret manager.

Writes and retries

Feed runs support Idempotency-Key. After a timeout on another write, read the resource or import-run state before retrying. Retry 429 and transient 5xx responses with capped exponential backoff and jitter.

Plans and quotas

Monthly API calls, import rows/runs, products, media storage, and background work depend on the workspace plan. A 402 response includes quota and reset details when available.

Expanded product pages

Product pages without expansions allow up to 100 rows. Any expand request is capped at 25 rows; continue with nextCursor.

Ready to connect product data?

Start on a paid plan, create an API key, and connect Avut-pim to your product workflow.

Credentials

Authorization: Bearer <API_KEY>
x-api-key: <API_KEY>

URL

GET https://api.avut.io/api/v1/products

Example

cURL

curl -sS "https://api.avut.io/api/v1/products?limit=50" \
  -H "Authorization: Bearer $AVUT_API_KEY"

Response example

{
  "data": [
    {
      "id": "prd_01J9Z7QH8V8C2P2K7A6X9M4D3E",
      "sku": "JACKET-NORDIC-001",
      "name": "Nordic performance jacket",
      "description": "Lightweight shell jacket for changing weather.",
      "status": {
        "id": "status_01J9Z7QH8V8C2P2K7A6X9M4D3E",
        "name": "Active",
        "code": "active"
      },
      "product_kind": "standard",
      "brand": {
        "id": "brand_01J9Z7QH8V8C2P2K7A6X9M4D3E",
        "name": "Avut Sample Brand",
        "code": "avut-sample-brand"
      },
      "supplier": {
        "id": "sup_01J9Z7QH8V8C2P2K7A6X9M4D3E",
        "name": "Avut Sample Supplier",
        "code": "avut-sample-supplier",
        "supplier_code": "SUP-100"
      },
      "product_group": {
        "id": "grp_01J9Z7QH8V8C2P2K7A6X9M4D3E",
        "name": "Jackets",
        "code": "jackets"
      },
      "packaging": {
        "roles": [
          {
            "role": {
              "id": "pkg_role_01J9Z7QH8V8C2P2K7A6X9M4D3E",
              "code": "consumer_unit",
              "name": "Consumer unit",
              "semantic": "consumer_unit",
              "isBaseLevel": true
            },
            "colli": {
              "index": 0,
              "label": "Colli 1",
              "description": null
            },
            "type": {
              "id": "pkg_type_01J9Z7QH8V8C2P2K7A6X9M4D3E",
              "name": "Polybag",
              "code": "polybag"
            },
            "gtin": "1234567890123",
            "additionalGtins": [],
            "quantityToConsumerUnit": "1",
            "dimensions": {
              "length": "45",
              "width": "35",
              "height": "8",
              "unit": "cm"
            },
            "volume": {
              "value": "12600",
              "unit": "cm3",
              "source": "derived"
            },
            "weights": {
              "net": "0.9",
              "gross": "1",
              "unit": "kg"
            }
          },
          {
            "role": {
              "id": "pkg_role_01J9Z7QH8V8C2P2K7A6X9M4D3F",
              "code": "master_carton",
              "name": "Master carton",
              "semantic": "master_carton",
              "isBaseLevel": false
            },
            "colli": {
              "index": 0,
              "label": "Colli 1",
              "description": null
            },
            "type": {
              "id": "pkg_type_01J9Z7QH8V8C2P2K7A6X9M4D3F",
              "name": "Brown box",
              "code": "brown_box"
            },
            "gtin": null,
            "additionalGtins": [],
            "quantityToConsumerUnit": "12",
            "dimensions": {
              "length": "60",
              "width": "40",
              "height": "30",
              "unit": "cm"
            },
            "volume": {
              "value": "72",
              "unit": "dm3",
              "source": "derived"
            },
            "weights": {
              "net": null,
              "gross": "8.4",
              "unit": "kg"
            }
          }
        ]
      },
      "eu_taric_code": "6201401000",
      "no_tariff_code": "62014000",
      "eu_antidumping_declarations": [],
      "tariff_signals": {
        "high_duty": {
          "status": "none",
          "source": "no",
          "code": "62014000",
          "duty": null,
          "threshold": 10
        },
        "anti_dumping": {
          "status": "none",
          "source": "taric",
          "code": "6201401000",
          "requires_declaration": false,
          "declarations_count": 0,
          "additional_codes": []
        }
      },
      "categories": [
        {
          "id": "cat_01J9Z7QH8V8C2P2K7A6X9M4D3E",
          "name": "Outerwear",
          "code": "outerwear"
        }
      ],
      "variant_model": {
        "id": "variant_model_01J9Z7QH8V8C2P2K7A6X9M4D3E",
        "name": "Color + Size",
        "code": "color_size"
      },
      "variant_parent": null,
      "variant_options": [
        {
          "dimension": {
            "id": "dim_01J9Z7QH8V8C2P2K7A6X9M4D3E",
            "name": "Size",
            "type": "size"
          },
          "option": {
            "id": "opt_01J9Z7QH8V8C2P2K7A6X9M4D3E",
            "name": "M"
          }
        }
      ],
      "archived_at": null,
      "updated_at": "2026-05-14T12:30:00.000Z",
      "gtin": "1234567890123",
      "product_template": {
        "id": "tpl_01J9Z7QH8V8C2P2K7A6X9M4D3E",
        "name": "Apparel"
      },
      "attributes": {
        "sample_color": "Black",
        "sample_material": "Recycled polyester"
      },
      "attribute_count": 2,
      "mediaSummary": {
        "count": 3,
        "primaryUrl": "https://cdn.example.com/products/jacket-original.jpg",
        "primaryThumbUrl": "https://cdn.example.com/products/jacket-thumb.jpg"
      },
      "mediaStatus": {
        "level": "ok",
        "issues": [],
        "mediaCount": 3,
        "primaryWidth": 1600,
        "primaryHeight": 2000,
        "rules": {
          "minPrimaryWidth": 800,
          "minPrimaryHeight": 800,
          "minImageCount": null
        }
      },
      "variantMediaCount": 0
    }
  ],
  "nextCursor": null,
  "limit": 50
}