DEVELOPERS · Integration API Reference

Fabrixa Integration API Reference

33 min read Last updated: 06-11-2026 119 views

The Integration API helps you create and manage Fabrixa orders, launch Fabrixa Studio, and stay in sync with production and fulfilment status via webhooks. The API follows REST conventions and uses JSON for all request and response bodies.

BASE URL

https://api.fabrixa.com/v2/integration

Send all requests to this base URL followed by the specific endpoint path. The base URL is the foundation for interacting with the Fabrixa API - retrieving, creating, updating, or deleting resources.

BEFORE YOUR FIRST REQUEST

Authentication

To access the Integration API, authenticate your requests using both an Application Access Token and an Application Key:

Authorization Header
Authorization: Bearer APPLICATION_ACCESS_TOKEN
Application Key Header
X-Application-Key: APPLICATION_KEY
Example cURL Command
curl -X 'GET' \
  'https://api.fabrixa.com/v2/integration/ping' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer APPLICATION_ACCESS_TOKEN' \
  -H 'X-Application-Key: APPLICATION_KEY'

Replace APPLICATION_ACCESS_TOKEN with your actual access token and APPLICATION_KEY with your actual application key.

HOW RESPONSES ARE STRUCTURED

Endpoints and Requests

The Integration API endpoints are organized by resource type and follow the RESTful architectural style. Each endpoint represents a resource, and actions on these resources are performed using standard HTTP methods.

All Integration API requests and responses are in JSON format, providing a consistent and easy-to-use interface for interacting with the API.

For full details on every endpoint, including request and response examples, see our Swagger documentation.

Response Format

All endpoints return data in a standardized format with these objects:

{
  "links": {
    "self": "https://api.fabrixa.com/v2/integration/products",
    "first_page": "https://api.fabrixa.com/v2/integration/products?page=1",
    "last_page": "https://api.fabrixa.com/v2/integration/products?page=2",
    "next_page": "https://api.fabrixa.com/v2/integration/products?page=2",
    "prev_page": null
  },
  "meta": {
    "total": 2,
    "current_page": 1,
    "per_page": 10
  },
  "data": [
    {
      "id": 1,
      "name": "Product 1",
      "description": "Description of Product 1"
    },
    {
      "id": 2,
      "name": "Product 2",
      "description": "Description of Product 2"
    }
  ]
}

Description of Response Objects

links

Contains pagination links to navigate through the results.

  • self — the URL of the current page.
  • first_page — the URL of the first page of results.
  • last_page — the URL of the last page of results.
  • next_page — the URL of the next page. null if there is no next page.
  • prev_page — the URL of the previous page. null if there is no previous page.

meta

Contains metadata about the response, such as pagination information.

  • total — the total number of items available across all pages.
  • current_page — the current page number of the results.
  • per_page — the number of items per page.

data

The main content of the response. data varies by endpoint - it can be a single object, for example one product, or an array of objects, for example a list of products.

WHEN SOMETHING GOES WRONG

Errors and Status Codes

All API requests return HTTP status codes that provide insight into the response.

400 Bad Request

The server cannot process the request due to validation errors - missing or invalid parameters.

401 Unauthorized

The client has not provided valid authentication credentials. Also returned when the access token has been revoked.

403 Forbidden

The server denied the request due to insufficient access rights, typically caused by incorrect or missing access permissions.

404 Not Found

The requested resource could not be found on the server.

412 Precondition Failed

The request cannot be applied to the resource in its current state, for example an order that can no longer be canceled.

429 Too Many Requests

The client has exceeded the allowable number of requests in a given timeframe. See Rate Limits.

5xx Errors

An internal server error occurred. Please contact Fabrixa support with details of the failed request.

Error Response Body

An example of an error response body:

{
    "links": {
        "self": "https://api.fabrixa.com/v2/integration/ping"
    },
    "meta": [],
    "errors": {
        "messages": [
            "Application Key is not specified."
        ]
    }
}

errors contains details about what failed. The messages array lists error descriptions. For a Bad Request, you will receive the names of the fields that failed validation.

KNOW YOUR REQUEST LIMITS

Rate Limits

The Integration API supports a limit of 30 requests per application per minute.

If you exceed this limit you will receive a 429 Too Many Requests response.

All Integration API responses include the X-RateLimit-Remaining header, how many requests the client can still make, and the X-RateLimit-Limit header, the total allowed per minute.

TEST BEFORE YOU GO LIVE

Sandbox Mode

Sandbox mode lets you test your integration end to end before any real order is produced or charged. It applies to your entire account: orders from every sales channel, including the Integration API and connected Shopify and WooCommerce stores, are not produced and not charged to your balance. Your account is in sandbox mode while its status is Pending Activation.

In sandbox mode you can:

To test orders, add products from the Fabrixa catalog: open a product, click Sell this and choose variants and designs. They then appear under My products.

To switch your account to sandbox mode, open the Platform, go to Settings → Company → Sandbox mode and click Switch to sandbox mode. You can also enable it when you add a new sales channel, including an Integration API channel, or email support@fabrixa.com and we will switch your account to sandbox mode for you. Sandbox mode is available to active accounts only.

When you are ready, activate your account yourself in the Platform under Settings → Company → Sandbox mode. You can also email support@fabrixa.com and we will activate it for you. Your connected stores and API credentials keep working, so nothing needs to be reconfigured.

Once activated, all new orders go to production and are charged to your balance. Orders created before activation remain test orders: they are never produced or charged, even after activation.

FIND WHAT TO SELL

Products

The catalog is everything Fabrixa produces. Your products are the catalog products you have added to your Fabrixa account, under your own names, descriptions, images and SKUs. An order row names a product variant - one size or version of a product - by its sku or variant_id: a variant of one of your products, or a catalog variant ordered directly.

SEE WHAT FABRIXA PRODUCES

Browse the Catalog

To list the products Fabrixa produces, send a GET request to https://api.fabrixa.com/v2/integration/catalog/products with your credentials. It lists the active products that have a variant a printing partner currently produces, and only those variants, each with its SKU, selling price, dimensions and option values.

Query Parameters

  • page and limit (up to 100) - paginate the list. Without them the whole catalog is returned in one response.
  • search - the products whose name contains the text, or whose slug or variant SKU starts with it.
  • category_id - the products in a category; parent_category_id - the products in any sub-category of a top-level category. See Catalog Categories.
  • group_id - the products in a catalog group.
  • sort_by - name, created, updated, type, popular or sold, in the sort_order asc or desc. By default the newest products come first.

Sample Request

curl -X 'GET' \
  'https://api.fabrixa.com/v2/integration/catalog/products?category_id=19&limit=10' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer APPLICATION_ACCESS_TOKEN' \
  -H 'X-Application-Key: APPLICATION_KEY'

Sample Response

{
    "links": {
        "self": "https://api.fabrixa.com/v2/integration/catalog/products",
        "first_page": "https://api.fabrixa.com/v2/integration/catalog/products?page=1",
        "last_page": "https://api.fabrixa.com/v2/integration/catalog/products?page=1",
        "next_page": null,
        "prev_page": null
    },
    "meta": {
        "total": 1,
        "current_page": 1,
        "per_page": 10
    },
    "data": [
        {
            "id": 1305,
            "name": "Duvet Cover",
            "subtitle": "Duvet Cover with a pillow",
            "description": "

Soft personalized duvet cover.

", "slug": "duvet-cover", "code": "DUVET-001", "HS_code": "63023100", "created_at": "2024-08-16T09:32:07.000000Z", "updated_at": "2024-08-16T09:38:50.000000Z", "is_sellable": true, "variants_min_selling_price": "29.95", "variants_max_selling_price": "49.95", "type": { "id": 5, "name": "Duvet cover" }, "status": { "id": 2, "name": "Active" }, "categories": [ { "id": 19, "name": "Duvet covers", "description": "Personalized duvet covers", "parent_category": { "id": 8, "name": "Bedroom", "description": "Bedroom products" } } ], "images": [ { "id": 5566, "url": "https://storage.googleapis.com/example/catalog/duvet-cover.jpg", "is_main": true, "created_at": "2024-08-16T09:32:07.000000Z", "screen_type_size": "large", "sort_number": 1 } ], "variants": [ { "id": 2705, "name": "Duvet Cover", "subtitle": "140x200", "description": null, "SKU": "COT864311", "selling_price": "29.95", "width": "140.00", "height": "200.00", "length": "2.00", "weight": "1.20", "created_at": "2024-08-06T11:23:44.000000Z", "updated_at": "2024-08-16T09:36:37.000000Z", "options": [ { "id": 151, "name": "Duvet Size", "values": [ { "id": 471, "value": "140x200" } ] } ] }, { "id": 2708, "name": "Duvet Cover", "subtitle": "200x220", "description": null, "SKU": "COT864314", "selling_price": "49.95", "width": "200.00", "height": "220.00", "length": "2.00", "weight": "1.80", "created_at": "2024-08-06T11:23:44.000000Z", "updated_at": "2024-08-16T09:37:11.000000Z", "options": [ { "id": 151, "name": "Duvet Size", "values": [ { "id": 474, "value": "200x220" } ] } ] } ] } ] }

Response Fields

  • id, name, subtitle, description (HTML), slug, code and HS_code, the customs tariff code.
  • is_sellable - whether the product is open for sales. A closed product is still listed, but an order for one of its variants is refused.
  • variants_min_selling_price and variants_max_selling_price - the price range across the listed variants.
  • type - the product type, which sets the print layers and the PDF page order; status - always Active in the catalog.
  • categories - the categories the product is in, each with its parent_category.
  • images - the product images, with url, is_main, screen_type_size and sort_number.
  • variants - the orderable versions of the product: id, name, subtitle, SKU, selling_price, the width, height, length and weight, and options, the option values that make this variant, for example its size.
FIND YOUR WAY AROUND

Catalog Categories

To list the categories the catalog is organised in, send a GET request to https://api.fabrixa.com/v2/integration/catalog/categories with your credentials. The response holds the top-level categories, each with its sub-categories nested in sub_categories and the number of catalog products it holds in products_count. Pass a category's id as category_id when browsing the catalog, or a top-level category's id as parent_category_id to get the products of all its sub-categories at once.

Query Parameters

  • page and limit (up to 100) - paginate the list. Without them every category is returned.
  • search - the categories whose name contains the text.
  • with_products_only - true leaves out the categories that hold no catalog product, directly or in a sub-category.
  • sort_by - category_name or category_created, in the sort_order asc or desc. By default the categories come in their catalog order.

Sample Request

curl -X 'GET' \
  'https://api.fabrixa.com/v2/integration/catalog/categories?with_products_only=true' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer APPLICATION_ACCESS_TOKEN' \
  -H 'X-Application-Key: APPLICATION_KEY'

Sample Response

{
    "links": {
        "self": "https://api.fabrixa.com/v2/integration/catalog/categories"
    },
    "meta": {
        "total": 1
    },
    "data": [
        {
            "id": 8,
            "name": "Bedroom",
            "description": "Bedroom products",
            "sort_number": 1,
            "slug": "bedroom",
            "products_count": 12,
            "sub_categories": [
                {
                    "id": 19,
                    "name": "Duvet covers",
                    "description": "Personalized duvet covers",
                    "sort_number": 1,
                    "slug": "duvet-covers",
                    "products_count": 7,
                    "images": [],
                    "sub_categories": []
                },
                {
                    "id": 20,
                    "name": "Pillows",
                    "description": "Personalized pillows and pillowcases",
                    "sort_number": 2,
                    "slug": "pillows",
                    "products_count": 4,
                    "images": [],
                    "sub_categories": []
                }
            ],
            "parent_category": null,
            "images": [
                {
                    "id": 781,
                    "url": "https://storage.googleapis.com/example/catalog/bedroom.jpg",
                    "is_main": true,
                    "created_at": "2024-08-16T09:32:07.000000Z",
                    "screen_type_size": "large",
                    "sort_number": 1
                }
            ]
        }
    ]
}
YOUR ACCOUNT

Your Products

To list the products in your account, send a GET request to https://api.fabrixa.com/v2/integration/products with your credentials. Your products are the catalog products you added to your Fabrixa account: they carry the names, descriptions and images you gave them there, and their variants the SKU values you chose. Only active products are listed, ten per page unless you pass limit.

Query Parameters

  • page and limit (up to 100) - the page to return and its size; the first page of ten by default.
  • search - the products whose name contains the text, or whose slug or variant SKU starts with it.

Sample Request

curl -X 'GET' \
  'https://api.fabrixa.com/v2/integration/products?search=duvet' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer APPLICATION_ACCESS_TOKEN' \
  -H 'X-Application-Key: APPLICATION_KEY'

Sample Response

{
    "links": {
        "self": "https://api.fabrixa.com/v2/integration/products",
        "first_page": "https://api.fabrixa.com/v2/integration/products?page=1",
        "last_page": "https://api.fabrixa.com/v2/integration/products?page=1",
        "next_page": null,
        "prev_page": null
    },
    "meta": {
        "total": 1,
        "current_page": 1,
        "per_page": 10
    },
    "data": [
        {
            "id": 5321,
            "name": "Dreamy Duvet Cover",
            "subtitle": "Duvet cover with a matching pillowcase",
            "description": "

Our personalized duvet cover, printed on soft cotton sateen.

", "slug": "dreamy-duvet-cover", "width": "50.00", "height": "50.00", "length": "20.00", "weight": "100.00", "created_at": "2025-03-04T10:12:40.000000Z", "updated_at": "2025-03-04T10:15:02.000000Z", "type": { "id": 5, "name": "Duvet cover", "description": "Duvet cover with pillow" }, "available_options": [ { "id": 151, "name": "Duvet Size", "values": [ { "id": 471, "value": "140x200" }, { "id": 474, "value": "200x220" } ] } ], "categories": [ { "id": 912, "name": "Bedding" } ], "collections": [ { "id": 77, "name": "Spring 2025" } ], "images": [ { "id": 48120, "is_main": true, "image_size": "1200x1200", "url": "https://storage.googleapis.com/example/shop/dreamy-duvet-cover.jpg", "screen_type_size": "large", "sort_number": 1 } ], "variants": [ { "id": 32323, "name": "Dreamy Duvet Cover", "subtitle": "140x200", "description": null, "SKU": "DDC-140200", "created_at": "2025-03-04T10:12:41.000000Z", "updated_at": "2025-03-04T10:12:41.000000Z", "options": [ { "id": 151, "name": "Duvet Size", "values": [ { "id": 471, "value": "140x200" } ] } ], "images": [], "available_source_types": ["duvet", "pillow", "pillow-back"], "required_source_types": ["duvet", "pillow"] }, { "id": 32326, "name": "Dreamy Duvet Cover", "subtitle": "200x220", "description": null, "SKU": "DDC-200220", "created_at": "2025-03-04T10:12:41.000000Z", "updated_at": "2025-03-04T10:12:41.000000Z", "options": [ { "id": 151, "name": "Duvet Size", "values": [ { "id": 474, "value": "200x220" } ] } ], "images": [], "available_source_types": ["duvet", "pillow", "pillow-back"], "required_source_types": ["duvet", "pillow"] } ] } ] }

To read one product, send a GET request to https://api.fabrixa.com/v2/integration/products/{product_id}, where {product_id} is its id. The response carries the same fields as the list. A product that is not in your account, even a catalog one, answers 404 Not Found with the message Product not found.

Response Fields

  • id, name, subtitle, description (HTML), slug, width, height, length and weight.
  • type - the product type, which sets the print layers and the PDF page order.
  • available_options - every option of the product with all its values, for example each size it comes in; each variant takes one value per option.
  • categories and collections - the categories and collections you sorted the product into in your account.
  • images - the product images, with url, is_main, image_size, screen_type_size and sort_number.
  • variants - the orderable versions of the product, see Product Variants: id, name, subtitle, SKU, options, images, and the print layers in available_source_types and required_source_types.
WHAT AN ORDER ROW NAMES

Product Variants

A variant is one orderable version of a product - one size, one colour - and what an order row names, by sku or by variant_id. To read a variant of one of your products, send a GET request to https://api.fabrixa.com/v2/integration/variants/{variant_id}, where {variant_id} is its id. A variant of a product that is not in your account answers 404 Not Found with the message Variant not found.

Sample Request

curl -X 'GET' \
  'https://api.fabrixa.com/v2/integration/variants/32323' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer APPLICATION_ACCESS_TOKEN' \
  -H 'X-Application-Key: APPLICATION_KEY'

Sample Response

{
    "links": {
        "self": "https://api.fabrixa.com/v2/integration/variants/32323"
    },
    "meta": [],
    "data": {
        "id": 32323,
        "name": "Dreamy Duvet Cover",
        "subtitle": "140x200",
        "description": null,
        "SKU": "DDC-140200",
        "created_at": "2025-03-04T10:12:41.000000Z",
        "updated_at": "2025-03-04T10:12:41.000000Z",
        "width": "140.00",
        "height": "200.00",
        "length": "2.00",
        "weight": "1.20",
        "options": [
            {
                "id": 151,
                "name": "Duvet Size",
                "values": [
                    {
                        "id": 471,
                        "value": "140x200"
                    }
                ]
            }
        ],
        "images": [],
        "product": {
            "id": 5321,
            "name": "Dreamy Duvet Cover",
            "subtitle": "Duvet cover with a matching pillowcase",
            "description": "

Our personalized duvet cover, printed on soft cotton sateen.

", "description2": null, "slug": "dreamy-duvet-cover", "created_at": "2025-03-04T10:12:40.000000Z", "updated_at": "2025-03-04T10:15:02.000000Z" }, "available_source_types": ["duvet", "pillow", "pillow-back"], "required_source_types": ["duvet", "pillow"] } }

Response Fields

  • id, name, subtitle, description, SKU, width, height, length, weight, options, images, and the product the variant belongs to.
  • available_source_types - the print layers of the variant, named as its production process knows them. Besides "file", which every variant takes for a PDF, these are the values a source's type may have; a product with a single print layer lists "print".
  • required_source_types - the layers a print file has to cover. A PDF sent as "file" covers them with its pages, in the page order of the product type. Otherwise the row needs a JPEG, PNG or TIFF file for each of them, with the layer's name as its type; a row that leaves one out is refused with 400 Bad Request and the names of the missing layers.

An order row for this variant, with a PDF whose pages are its layers:

"rows": [
    {
        "sku": "DDC-140200",
        "quantity": 1,
        "sources": [
            {
                "type": "file",
                "url": "https://samples-files.com/samples/duvet-cover.pdf"
            }
        ]
    }
]

Which Variants Can Be Ordered

  • An order row may name a variant of a product in your account, or a catalog variant directly, never a product of another client. The variant is matched by its variant_id, or by its sku whatever the case of the letters.
  • The variant has to be active, and its product active and open for sales. For your copy of a catalog product, the catalog product has to be active and the catalog variant switched on as well.
  • Otherwise the order is refused with 400 Bad Request and the reason, for the row in question: The variant not found., The product is not active., The catalog product is not active., The product is not open for sales., The variant is not active. or The catalog variant is not active.
CREATE AND TRACK ORDERS

Orders

Create orders in Fabrixa from your own storefront or platform, attach the required print files, and follow each item as it moves through fulfilment.

PREPARE YOUR ORDER DATA

Create an Order

To create an order via the Fabrixa Integration API, send a POST request to https://api.fabrixa.com/v2/integration/orders. The request body must include:

Request Body Structure

  • number (optional) - the order number. If not provided, a unique number is generated.
  • comments (optional) - any additional comments or notes related to the order.
  • purchased_at - date and time when the order was purchased, formatted as YYYY-MM-DD HH:MM:SS.
  • client_ip (optional) - the IP address of the customer.
  • client_user_agent (optional) - the user-agent string of the customer.
  • rows - array of order items, each containing:
    • sku - the SKU of the product variant. See Swagger for details.
    • quantity - quantity of the product variant ordered.
    • client_barcode (optional) - unique client-side identifier per order line, formatted as Code 128.
    • cart_item_key (required without sources) - unique identifier from the platform embedding Fabrixa Studio, used to associate saved customizations with the order.
    • sources (required without cart_item_key) - array of source files associated with the product, each containing:
      • type - "file" for a PDF, or "print" for a JPEG, PNG or TIFF file.
      • url - URL of the source file.
  • customer - customer details:
    • first_name, last_name, email, phone.
  • shipping_address - shipping details:
    • address, address2 (optional), address3 (optional).
    • city, country_code (ISO 3166-2), country, postal_code, state (optional).
    • first_name, last_name, phone (optional), company (optional).
  • shipping_label (optional) - label details:
    • method_name - e.g. "Post NL".
    • tracking_number, tracking_url, label_pdf_url.
    • date_created - formatted as YYYY-MM-DD HH:MM:SS.

Sample Request

{
  "number": "NL2024010201",
  "comments": "Customer agrees with a low resolution file.",
  "purchased_at": "2024-06-26 21:12:22",
  "client_ip": "127.0.0.1",
  "client_user_agent": "Mozilla",
  "rows": [
    {
      "variant_id": 2705,
      "quantity": 1,
      "client_barcode": "1234567890",
      "sources": [
        {
          "type": "file",
          "url": "https://samples-files.com/samples/sample.pdf"
        }
      ]
    }
  ],
  "customer": {
    "first_name": "John",
    "last_name": "Doe",
    "email": "3VJtP@example.com",
    "phone": "0612345678"
  },
  "shipping_address": {
    "address": "Voorbeeldstraat",
    "address2": "17",
    "city": "Amsterdam",
    "country_code": "NL",
    "country": "Netherlands",
    "postal_code": "1012 AB",
    "state": "North Holland",
    "first_name": "John",
    "last_name": "Doe",
    "phone": "0612345678"
  },
  "shipping_label": {
    "method_name": "Post NL",
    "tracking_number": "3SABCD1234567",
    "tracking_url": "https://postnl.nl/tracktrace/3SABCD1234567",
    "label_pdf_url": "https://api.fabrixa.com/storage/8966630826422f36d822f91680012141.pdf",
    "date_created": "2024-01-01 00:00:00"
  }
}

Sample Response

{
    "links": {
        "self": "https://api.fabrixa.com/v2/integration/orders"
    },
    "meta": [],
    "data": {
        "id": 20338,
        "number": "NL2024010201",
        "comments": "Customer agrees with a low resolution file.",
        "is_archived": false,
        "status": "imported",
        "fulfillment_status": "unfulfilled",
        "purchased_at": "2024-06-26T21:12:22.000000Z",
        "created_at": "2024-06-26T21:15:03.000000Z",
        "updated_at": "2024-06-26T21:15:04.000000Z",
        "rows": [
            {
                "id": 41600,
                "quantity": 1,
                "client_barcode": "1234567890",
                "fulfillment_status": "unfulfilled",
                "variant": {
                    "id": 2705,
                    "name": "Duvet Cover",
                    "subtitle": "140x200",
                    "SKU": "COT864311",
                    "product": {
                        "id": 1305,
                        "name": "Duvet Cover",
                        "subtitle": "Duvet Cover with a pillow"
                    }
                },
                "sources": [
                    {
                        "type": "file",
                        "url": "https://samples-files.com/samples/sample.pdf",
                        "properties": null
                    }
                ]
            }
        ],
        "shipments": [],
        "customer": {
            "email": "3VJtP@example.com",
            "first_name": "John",
            "last_name": "Doe",
            "phone": "0612345678"
        },
        "shipping_address": {
            "address": "Voorbeeldstraat",
            "address2": "17",
            "address3": null,
            "city": "Amsterdam",
            "country": "Netherlands",
            "country_code": "NL",
            "company": null,
            "first_name": "John",
            "last_name": "Doe",
            "phone": "0612345678",
            "state": "North Holland",
            "postal_code": "1012 AB"
        }
    }
}
CHANGE ORDER DETAILS

Update an Order

To update an order, send a PATCH request to https://api.fabrixa.com/v2/integration/orders/{order_id}, where {order_id} is the Fabrixa order id. Only the fields you send are changed, and the order status stays as it is. The response contains the updated order. You can change:

  • number, comments, purchased_at, client_ip, client_user_agent.
  • customer - first_name, last_name, email, phone.
  • shipping_address - the same fields as when creating an order.

Sample Request

{
  "comments": "Deliver to the neighbours if nobody is home.",
  "shipping_address": {
    "address": "Voorbeeldstraat",
    "address2": "19",
    "city": "Amsterdam",
    "country_code": "NL",
    "country": "Netherlands",
    "postal_code": "1012 AB",
    "first_name": "John",
    "last_name": "Doe",
    "phone": "0612345678"
  }
}

Sample Response

{
    "links": {
        "self": "https://api.fabrixa.com/v2/integration/orders/20338"
    },
    "meta": [],
    "data": {
        "id": 20338,
        "number": "NL2024010201",
        "comments": "Deliver to the neighbours if nobody is home.",
        "is_archived": false,
        "status": "imported",
        "fulfillment_status": "unfulfilled",
        "purchased_at": "2024-06-26T21:12:22.000000Z",
        "created_at": "2024-06-26T21:15:03.000000Z",
        "updated_at": "2024-06-27T09:41:18.000000Z",
        "rows": [
            {
                "id": 41600,
                "quantity": 1,
                "client_barcode": "1234567890",
                "fulfillment_status": "unfulfilled",
                "variant": {
                    "id": 2705,
                    "name": "Duvet Cover",
                    "subtitle": "140x200",
                    "SKU": "COT864311",
                    "product": {
                        "id": 1305,
                        "name": "Duvet Cover",
                        "subtitle": "Duvet Cover with a pillow"
                    }
                },
                "sources": [
                    {
                        "type": "file",
                        "url": "https://samples-files.com/samples/sample.pdf",
                        "properties": null
                    }
                ]
            }
        ],
        "shipments": [],
        "customer": {
            "email": "3VJtP@example.com",
            "first_name": "John",
            "last_name": "Doe",
            "phone": "0612345678"
        },
        "shipping_address": {
            "address": "Voorbeeldstraat",
            "address2": "19",
            "address3": null,
            "city": "Amsterdam",
            "country": "Netherlands",
            "country_code": "NL",
            "company": null,
            "first_name": "John",
            "last_name": "Doe",
            "phone": "0612345678",
            "state": "North Holland",
            "postal_code": "1012 AB"
        }
    }
}
  • Order rows cannot be changed: a request with rows is rejected with 400 Bad Request. To change the items, cancel the order and create a new one.
  • An order with the status on hold cannot be updated; the API responds with 412 Precondition Failed.
{
    "links": {
        "self": "https://api.fabrixa.com/v2/integration/orders/20338"
    },
    "meta": [],
    "errors": {
        "rows": [
            "Order rows cannot be changed. Cancel the order and create a new one."
        ]
    }
}
STOP AN ORDER

Cancel an Order

To cancel an order, send a POST request without a body to https://api.fabrixa.com/v2/integration/orders/{order_id}/cancel, where {order_id} is the Fabrixa order id (the numeric id field of the order), not your order number. The response contains the order with the status canceled, and an order.updated webhook is sent.

  • An order can be canceled while its status is created, imported, accepted or on hold and its fulfillment_status is still unfulfilled. Once it becomes scheduled, production has started and the order can no longer be canceled.
  • The charges for a canceled order are refunded to your balance.
  • Canceling an order that is already canceled returns it unchanged, so the request is safe to retry.

Sample Response

{
    "links": {
        "self": "https://api.fabrixa.com/v2/integration/orders/20338/cancel"
    },
    "meta": [],
    "data": {
        "id": 20338,
        "number": "NL2024010201",
        "comments": "Customer agrees with a low resolution file.",
        "is_archived": false,
        "status": "canceled",
        "fulfillment_status": "unfulfilled",
        "purchased_at": "2024-06-26T21:12:22.000000Z",
        "created_at": "2024-06-26T21:15:03.000000Z",
        "updated_at": "2024-06-27T10:02:45.000000Z",
        "rows": [
            {
                "id": 41600,
                "quantity": 1,
                "client_barcode": "1234567890",
                "fulfillment_status": "unfulfilled",
                "variant": {
                    "id": 2705,
                    "name": "Duvet Cover",
                    "subtitle": "140x200",
                    "SKU": "COT864311",
                    "product": {
                        "id": 1305,
                        "name": "Duvet Cover",
                        "subtitle": "Duvet Cover with a pillow"
                    }
                },
                "sources": [
                    {
                        "type": "file",
                        "url": "https://samples-files.com/samples/sample.pdf",
                        "properties": null
                    }
                ]
            }
        ],
        "shipments": [],
        "customer": {
            "email": "3VJtP@example.com",
            "first_name": "John",
            "last_name": "Doe",
            "phone": "0612345678"
        },
        "shipping_address": {
            "address": "Voorbeeldstraat",
            "address2": "17",
            "address3": null,
            "city": "Amsterdam",
            "country": "Netherlands",
            "country_code": "NL",
            "company": null,
            "first_name": "John",
            "last_name": "Doe",
            "phone": "0612345678",
            "state": "North Holland",
            "postal_code": "1012 AB"
        }
    }
}

If the order cannot be canceled, the API responds with 412 Precondition Failed and a message explaining why: its current status does not allow it (the status is named in the message), or production has already started.

{
    "links": {
        "self": "https://api.fabrixa.com/v2/integration/orders/20338/cancel"
    },
    "meta": [],
    "errors": {
        "messages": [
            "This order cannot be canceled in its current status (ready for shipping)."
        ]
    }
}
FROM IMPORT TO DELIVERY

Order Lifecycle

An order is tracked with three statuses: the order status, its production status fulfillment_status and the status of each shipment in shipments. Every change is sent in the order.updated webhook and returned by GET /orders/{order_id}.

Order Statuses

The status of an order, in the order it is reached:

Fulfillment Statuses

The fulfillment_status of an order and of each order row, in the order it is reached. It only moves forward, never back:

An order as a whole is never rejected. A single item can be rejected in the quality check during production. It is then printed again: it returns to unfulfilled and goes through production once more, while the order keeps its status and continues once the item is finished.

Shipment Statuses

The status of each shipment in shipments, in the order it is reached:

Exceptions:

TRACK YOUR ORDER ITEMS

Track Fulfillment

To get the fulfilment status for a specific order, send a GET request to https://api.fabrixa.com/v2/integration/orders/{order_id}/fulfillments. The response provides a list of fulfilments associated with the order, including each item status, product details, and production-step progress.

Sample Response

{
    "data": [
        {
            "id": 1499,
            "barcode": "1200004169200",
            "status": "unfulfilled",
            "created_at": "2024-08-19T12:38:59.000000Z",
            "updated_at": "2024-08-19T12:39:00.000000Z",
            "variant": {
                "id": 32327,
                "name": "Test iAPI blanket product",
                "subtitle": "100 x 150 cm",
                "SKU": "COF099191"
            },
            "product": {
                "id": 1306,
                "name": "Test iAPI blanket product",
                "subtitle": "Test iAPI blanket product"
            },
            "production_steps": [
                {
                    "id": 5,
                    "name": "Print duvet",
                    "description": "Printing the duvet according to the specified design and dimensions.",
                    "status": {
                        "value": "pending",
                        "notes": null,
                        "updated_at": null
                    }
                },
                {
                    "id": 6,
                    "name": "Print pillow",
                    "description": "Printing the pillow cover with the assigned design.",
                    "status": {
                        "value": "pending",
                        "notes": null,
                        "updated_at": null
                    }
                }
            ]
        }
    ]
}

The response includes a list of fulfilments, each providing:

  • id - unique identifier for the fulfilment.
  • barcode - barcode for internal tracking and identification; can also be printed on the product.
  • status - the current fulfilment status: unfulfilled or fulfilled.
  • created_at and updated_at - timestamps for fulfilment creation and last update.
  • variant - detailed information about the product variant: name, subtitle, SKU.
  • product - product details: name, subtitle.
  • production_steps - array of production steps. The list of steps depends on the product type. For each step:
    • id - unique identifier for the production step.
    • name - e.g. "Print duvet".
    • description - what the production step entails.
    • status - the current status:
      • pending - not yet started.
      • in progress - currently underway.
      • rejected - the step encountered an issue and was not completed successfully.
      • done - the step has been completed.
    • notes - any additional notes related to the step.
    • updated_at - the last time the step status was updated.

Each fulfilment record corresponds to a specific product or product variant within the order, and each copy of the product in the order has its own fulfilment record - every item is tracked individually throughout production.

If no fulfilments are returned for an order, the order has not yet entered the processing stage.

HOW TO PROVIDE PRINT FILES

Source File Requirements

When including source files in your order, ensure they meet the following requirements:

type

PDF is the preferred source format. For a product with a single print layer, such as a blanket or a towel, a JPEG, PNG or TIFF file works as well. For a product with several layers, provide a PDF file with each layer as a separate page: during processing each page is treated as an individual layer, so a multi-layer design is submitted as a single source file. See PDF requirements and page order.

Set the type by the file format. For a PDF, use "file": each page is printed on one layer of the product, in the page order listed for that product. For a JPEG, PNG or TIFF file, which suits a product with a single print layer, use "print".

"sources": [
    {
        "type": "file",
        "url": "https://samples-files.com/samples/source.pdf"
    }
]

For further details, see the Swagger documentation.

url

The url field must contain a direct link to the source file. Ensure the URL is accessible and the file can be downloaded without authentication. The link must remain accessible throughout the production process.

How We Download the File

We download the file from your server twice: a request with Range: 0-0 while the order is validated, then the whole file. Both requests send the User-Agent Fabrixa/2.0 (+https://api.fabrixa.com/docs/integration#sources; print file fetch); if your site filters automated traffic, allow it. The URL must use HTTPS on port 443 and return the file directly, without redirects, with the file's real Content-Type, e.g. application/pdf. Each request times out after 60 seconds.

File Format

Provide a PDF file, or for a single-layer product a JPEG, PNG or TIFF file, served with its real Content-Type. Transparent areas of a PNG are printed white. Ensure images are high-quality and suitable for printing.

Image Dimensions

Maximum dimensions are 15,000 pixels on either side. Images exceeding this limit may be resized or rejected. Image resolution should match product dimensions; otherwise images may be resized or cropped to fit.

Resolution

No specific resolution requirement - just ensure image quality is sufficient for printing.

Color Space

Images should be in RGB color space for accurate colour representation. Other colour spaces will be converted during processing, which may result in incorrect colours.

File Size

Each source file can be up to 200 MB. A larger file is rejected: when the order is created if your server sends a Content-Length, otherwise when the file is downloaded.

PDF Requirements and Page Order

The order of pages in the PDF is important. Pages are matched to product layers by position, and the expected page order depends on the product type. Make sure the pages in your PDF follow the correct layer sequence for the product you are submitting.

ProductPDF page order
Duvet Cover
  1. Duvet cover
  2. Pillow front
  3. Pillow back
Curtains
  1. Left curtain
  2. Right curtain
T-shirt
  1. Front
  2. Back
  3. Left sleeve
  4. Right sleeve
  5. Collar
Tanktop
  1. Front
  2. Back
  3. Left sleeve
  4. Right sleeve
  5. Collar
Sweater
  1. Front
  2. Back
  3. Left sleeve
  4. Right sleeve
  5. Left cuff
  6. Right cuff
  7. Collar
  8. Waistband
Hoodie
  1. Front
  2. Back
  3. Left sleeve
  4. Right sleeve
  5. Left cuff
  6. Right cuff
  7. Hood inside left
  8. Hood inside right
  9. Hood outside left
  10. Hood outside right
  11. Waistband
  12. Pocket lower left
  13. Pocket lower right
  14. Pocket upper right
  15. Pocket upper left
Sweatpants
  1. Front right
  2. Front left
  3. Back left
  4. Back right
  5. Left cuff
  6. Right cuff
  7. Waistband
  8. Right pocket
  9. Left pocket
  10. Back pocket
  11. Back pocket interfacing
Sweatshorts
  1. Front right
  2. Front left
  3. Back left
  4. Back right
  5. Waistband
  6. Right pocket
  7. Left pocket

Important: each PDF page must match the required dimensions for its product layer and be oriented correctly. Place the artwork so the top of the design aligns with the top of the page. Incorrect page size or orientation may cause scaling, rotation, or alignment issues in production.

PLAN THE DELIVERY

Shipping

Know what shipping an order will cost and how long it will be under way before you place it, priced by the same rules Fabrixa applies to the order itself.

WHERE IT SHIPS

Shipping Countries

To find out which countries a product variant can be shipped to, send a GET request to https://api.fabrixa.com/v2/integration/shipping/countries with your credentials. The list holds the countries the location producing the variant has a shipping rate to, for a shipping package the variant can be packed into, sorted by name. A country that is not listed has no shipping rate for the variant.

Query Parameters

  • variant_id or sku - the variant, named as in an order row, as for an estimate.

Sample Request

curl -X 'GET' \
  'https://api.fabrixa.com/v2/integration/shipping/countries?sku=DDC-140200' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer APPLICATION_ACCESS_TOKEN' \
  -H 'X-Application-Key: APPLICATION_KEY'

Sample Response

{
    "links": {
        "self": "https://api.fabrixa.com/v2/integration/shipping/countries"
    },
    "meta": {
        "total": 2
    },
    "data": [
        {
            "code": "BE",
            "name": "Belgium",
            "min_shipping_price": "7.75",
            "max_shipping_price": "9.85",
            "currency": "EUR",
            "min_eta_days": 1,
            "max_eta_days": 2
        },
        {
            "code": "NL",
            "name": "Netherlands",
            "min_shipping_price": "6.70",
            "max_shipping_price": "8.40",
            "currency": "EUR",
            "min_eta_days": 1,
            "max_eta_days": 1
        }
    ]
}

Response Fields

  • code and name - the country, with the ISO 3166-1 alpha-2 code to pass as country_code to the estimate.
  • min_shipping_price and max_shipping_price - the range of what one shipping package costs to the country, excluding VAT, in currency, across the packages the variant can be packed into. An order of several units may need several packages, so ask for an estimate for the price of a given quantity.
  • min_eta_days and max_eta_days - the range of days a package is under way once handed to the carrier, production time not included; null when the rates carry no delivery estimate.
BEFORE YOU ORDER

Estimate Shipping

To find out what shipping a product variant would cost and how long it would be under way, send a GET request to https://api.fabrixa.com/v2/integration/shipping/estimate with your credentials. The estimate follows the rules an order is priced by: the units are packed into the shipping packages of the location producing the variant, and each package is priced along the route from that location to the destination country. Nothing is ordered or reserved, and an order is priced when it is placed, so its shipping can differ if the rates change in between.

Query Parameters

  • variant_id or sku - the variant, named as in an order row: a variant of one of your products, or a catalog variant. It has to be one you can order.
  • country_code - the ISO 3166-1 alpha-2 code of the country the order ships to, for example NL.
  • quantity - the number of units, from 1 to 1000.

Sample Request

curl -X 'GET' \
  'https://api.fabrixa.com/v2/integration/shipping/estimate?sku=DDC-140200&country_code=NL&quantity=2' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer APPLICATION_ACCESS_TOKEN' \
  -H 'X-Application-Key: APPLICATION_KEY'

Sample Response

{
    "links": {
        "self": "https://api.fabrixa.com/v2/integration/shipping/estimate"
    },
    "meta": [],
    "data": {
        "variant_id": 32323,
        "sku": "DDC-140200",
        "quantity": 2,
        "country_code": "NL",
        "origin_country": {
            "code": "PT",
            "name": "Portugal"
        },
        "packages_count": 1,
        "packages": [
            {
                "package_type": "Small Box",
                "length": 30,
                "width": 20,
                "height": 10,
                "quantity": 1,
                "price": "7.45",
                "eta_days": 3
            }
        ],
        "shipping_price": "7.45",
        "currency": "EUR",
        "eta_days": 3
    }
}

Response Fields

  • variant_id, sku, quantity and country_code - the variant, quantity and destination the estimate is for.
  • origin_country - the country the variant ships from, with its code and name.
  • packages_count - the number of shipping packages the units are packed into.
  • packages - the packages themselves, one entry per package type: the package_type, its length, width and height in cm, the quantity of such packages, the price of shipping one of them and its eta_days. The prices times the quantities add up to shipping_price.
  • shipping_price - the shipping price of all the packages together, excluding VAT, in currency. A route without a shipping rate ships for free, as it would for an order, and is priced 0.00.
  • eta_days - the number of days the slowest package is under way once handed to the carrier, production time not included; null when the route has no delivery estimate.

A request that fails validation is answered with 400 Bad Request and the reason for each field, with the same messages as an order row, for example The variant not found. When no shipping package can carry the units, the answer is 400 Bad Request with the message No shipping package can carry the variant.

PRODUCT CUSTOMIZATION

Fabrixa Studio

Fabrixa Studio is a tool that lets users seamlessly customize and personalize products in real time with an intuitive interface where users can create or upload their own designs.

Fabrixa Studio is ideal for businesses offering custom products - enabling customers to visualize their designs before finalizing orders.

ADD STUDIO TO YOUR SHOP

Embed Fabrixa Studio

You can embed Fabrixa Studio into your website using an iframe. This enables your customers to personalize products directly on your site during checkout.

Example iframe for embedding Fabrixa Studio:

<iframe id="fabrixa-studio"
    src="https://studio.fabrixa.com?application_key={application_key}&sku={product_sku}&cart_item_key={cart_item_key}"
    name="FabrixaStudio"
    scrolling="no"
    frameborder="1"
    width="100%"
    height="100%"
    allowfullscreen="">
</iframe>

Replace the values for product_sku, cart_item_key, and application_key with your dynamic values.

Studio's header shows the product's name as it is in your shop - the same title your customers see - with the chosen variant's options under it. It is your shop's own copy of the product, so a name you edit in Fabrixa shows in Studio too; locale does not translate it.

Request to Create an Order with cart_item_key

{
  "number": "NL2024010201",
  "purchased_at": "2024-06-26 21:12:22",
  "client_ip": "127.0.0.1",
  "client_user_agent": "Mozilla",
  "rows": [
    {
      "sku": "SB796162",
      "quantity": 1,
      "cart_item_key": "0cb76770-de2d-4524-aa48-47b6e5f0d8a5"
    }
  ],
  "customer": {
    "...": "..."
  },
  "shipping_address": {
    "...": "..."
  },
  "shipping_label": {
    "...": "..."
  }
}
LISTEN FOR CUSTOMER ACTIONS

Handle Studio Events

When the Add to Cart button is clicked inside the iframe, the following command is executed:

window.parent.postMessage('customizationFinished', '*');

Similarly, when the Back button is clicked:

window.parent.postMessage('closeButtonClicked', '*');

The postMessage method facilitates cross-origin communication between the iframe and its parent window, allowing it to notify the parent about specific user actions.

The first argument of postMessage is the data you want to send. The string 'customizationFinished' indicates the user has finalized customization and is adding the product to the cart. 'closeButtonClicked' indicates the user has chosen to go back.

In the parent window, listen for these messages using the message event listener:

window.addEventListener('message', function(event) {
    if (event.origin === 'https://studio.fabrixa.com') {
        if (event.data === 'customizationFinished') {
            // Handle the Add to Cart event
            console.log('Customization finished and item can be added to cart.');
        } else if (event.data === 'closeButtonClicked') {
            // Handle the Back button event
            console.log('Back button clicked.');
        }
    }
});

Always check the origin of incoming messages to ensure they come from a trusted source. Depending on the message received, perform the necessary actions - update the user interface, process the cart, etc. Validating origin is crucial for security - it prevents unauthorized scripts from interacting with your application.

SHOW THE FINISHED DESIGN

Customization Preview

After customization is completed, display the final design using the preview URL below. This URL returns an image of the customized product, suitable as the src value in an <img> tag. Ideal for showing the customized product in your cart, order summary, or anywhere in your shop interface.

https://api.fabrixa.com/v2/studio/customizations/{CART_ITEM_KEY}/preview?Application-Key={APPLICATION_KEY}

Replace {CART_ITEM_KEY} with the actual cart item key and {APPLICATION_KEY} with your valid application key.

Example usage in an image tag:

<img
    src="https://api.fabrixa.com/v2/studio/customizations/{CART_ITEM_KEY}/preview?Application-Key={APPLICATION_KEY}"
    alt="Customized Product Preview"
    style="max-width: 100%; height: auto;" />
TRY IT WITH YOUR VALUES

Live Demo

The customization preview will appear here after the design is finished.

Customization preview
RECEIVE EVENT UPDATES

Webhooks

Webhooks are used by Fabrixa to notify your system about real-time events - order updates or creations. When an event occurs, Fabrixa sends a webhook to your server containing the relevant information. Your server must expose a public POST endpoint to handle incoming webhooks.

REVIEW YOUR INCOMING HEADERS

Webhook Request Headers

The webhook request includes the following headers to help you identify and validate the incoming request:

{
  "content-type": "application/json",
  "user-agent": "Fabrixa/2.0 (+https://api.fabrixa.com/docs/integration#webhooks; webhook)",
  "x-webhook-signature": "YmEwNjBhMGMyMzE3ZWQ5NGQ5NDYwOGVhNzNhMjQ4M2MyODZkZmI3NTQ1YzYxYjdkMzNhZjgzYzBmMTkxYTAxMw==",
  "x-webhook-topic": "order.updated"
}
Header Breakdown

Webhooks are sent with the User-Agent Fabrixa/2.0 (+https://api.fabrixa.com/docs/integration#webhooks; webhook); if your endpoint filters automated traffic, allow it. To be sure a request comes from Fabrixa, verify x-webhook-signature.

CHOOSE YOUR EVENT TOPICS

Webhook Events

Fabrixa webhooks notify your system of changes in order status or activity. Each webhook is triggered by a specific x-webhook-topic value. Currently supported topics:

TopicDescription
order.created Triggered when a new order is placed in Fabrixa, either via API request or directly in the platform.
order.updated Triggered when order details such as the order status or fulfilment status are updated.
INSPECT YOUR EVENT PAYLOAD

Webhook Payload Example

An example of the payload sent with the webhook. This payload represents an order update:

{
  "id": 23069,
  "number": "1250211835",
  "comments": null,
  "is_archived": false,
  "status": "accepted",
  "fulfillment_status": "fulfilled",
  "purchased_at": "2025-04-17T16:17:21.000000Z",
  "created_at": "2025-04-17T16:17:23.000000Z",
  "updated_at": "2025-04-18T07:43:52.000000Z",
  "rows": [
    {
      "id": 27954,
      "quantity": 1,
      "client_barcode": "1250211835",
      "fulfillment_status": "fulfilled",
      "variant": {
        "id": 293457,
        "name": "Sherpa fleece deken",
        "subtitle": "100x150",
        "SKU": "SFD787231",
        "product": {
          "id": 5319,
          "name": "Sherpa fleece deken",
          "subtitle": "Sherpa fleece deken"
        }
      },
      "sources": [
        {
          "type": "print",
          "url": "https://storage.googleapis.com/fabrixa-api/storage/99b10aaa-df4d-47e4-9bc9-b1d6a785df4c/orders/merchandise-sources/120002795400.pdf",
          "properties": {
            "fill_style": "contain"
          }
        }
      ]
    }
  ],
  "shipments": [
    {
      "id": 4182,
      "carrier": "PostNL",
      "method": "Standard",
      "status": "registered",
      "tracking_number": "3SABCD1234567",
      "tracking_url": "https://jouw.postnl.nl/track-and-trace/3SABCD1234567-NL-1012AB",
      "packages": [
        {
          "tracking_number": "3SABCD1234567",
          "tracking_url": "https://jouw.postnl.nl/track-and-trace/3SABCD1234567-NL-1012AB"
        }
      ],
      "expected_delivery_date": "2025-04-22",
      "created_at": "2025-04-18T07:43:50.000000Z"
    }
  ]
}

Once the order ships, shipments lists each shipment with its carrier, shipping method, status (pending, registered, collected, in transit, delivered, failed, returned or canceled) and tracking: tracking_number and tracking_url, and the same for each package in packages when a shipment has several. An order.updated webhook is sent whenever a shipment's status or tracking changes, and GET /orders/{order_id} returns the same field.

VERIFY YOUR WEBHOOK SOURCE

Verify Webhook Signatures

To ensure the webhook request is authentic and untampered, verify the x-webhook-signature header. This involves recalculating the HMAC-SHA256 signature using the raw request payload and your secret key, then comparing it to the received signature.

Raw PHP Example

$payload = file_get_contents('php://input');
$yourSecret = 'your-secret-key';
$expectedSignature = base64_encode(hash_hmac('sha256', $payload, $yourSecret, true));
$receivedSignature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';

if (!hash_equals($expectedSignature, $receivedSignature)) {
    http_response_code(403);
    exit('Invalid signature');
}

Laravel Example

public function handle(Request $request)
{
    $yourSecret = 'your-secret-key';
    $payload = $request->getContent();
    $expectedSignature = base64_encode(hash_hmac('sha256', $payload, $yourSecret, true));
    $receivedSignature = $request->header('x-webhook-signature');

    if (!hash_equals($expectedSignature, $receivedSignature)) {
        abort(403, 'Invalid signature');
    }

    // Continue processing...
}

Replace $yourSecret with your shared secret key. Always use hash_equals for comparing signatures to mitigate timing attacks.

WHAT IF DELIVERY FAILS?

Webhook Retries

Webhooks are disabled after 10 unsuccessful delivery attempts by default. If your endpoint returns an unsuccessful status such as 404 or any 5xx error, the webhook will retry for a total of 10 times. If it continues to return a non-2xx or non-3xx response code, it will be deactivated. Successful responses include:

RETURN A CLEAR RESPONSE

Webhook Response

We strongly recommend your endpoint returns a 200 OK status code as quickly as possible to acknowledge successful receipt of the webhook. While any 2xx or 3xx response is considered successful, 200 is the most commonly used and reliable.

To avoid delivery timeouts or retries, return 200 OK immediately and handle webhook payload processing asynchronously, for example via a background job or queue. If your endpoint takes too long to respond, it may be considered a failure even if the response is ultimately successful.

Responses with status codes in the 4xx or 5xx range, or timeouts, will trigger retries according to the retry mechanism.