Skip to content
Docs

Keep your shop’s catalog in Emailit for product grids, recommendations and order items.

Base URLhttps://api.emailit.com/v2AuthenticationErrorsRate limits

Create or update a product

Add a product to your catalog, or update it if a product with the same id already exists. The id is the product ID in your shop, so you can send the same product again whenever it changes. Requires an API key with the full or events scope. With an events key, the response holds only object, id and external_id.

id is always required, and title is required for a new product. Fields are written only when you send them, so a product you send again with just a new price keeps its title, categories, image and the rest. To send many products at once, use Create or update products in bulk.

Product grids, recommendations and order items in emails read from the catalog. See Products, coupons and the cart.

POST/products

Request Body

idstring | numberRequired

The product ID in your shop, up to 255 characters. Numbers are stored as strings. Stored as external_id. You can also send it as external_id.

titlestring

Product name, up to 500 characters. You can also send it as name. Required for a new product.

skustring

Stock keeping unit, up to 255 characters.

descriptionstring

Product description, up to 10,000 characters.

urlstring

Product page in your shop. An http or https URL, up to 2,048 characters.

image_urlstring

Product image. An http or https URL, up to 2,048 characters.

pricenumber | string

Current price, as a number or a numeric string such as "89.00". Can’t be negative. Stored with up to 4 decimal places.

compare_at_pricenumber | string

Price before a discount, in the same format as price. When it’s higher than price, the product counts as on sale.

currencystring

Three-letter ISO 4217 code, such as USD or EUR. Lowercase is accepted. Emails format the product’s prices in this currency, or in USD when it isn’t set.

categoriesstring[]

Up to 50 category names of up to 191 characters each. Duplicates are removed.

brandstring

Brand name, up to 191 characters.

inventory_quantityinteger | null

Units in stock. null means you don’t track stock. Product grids in emails leave out products at 0.

statusstring

active or archived. New products are active. Archived products are hidden from List products by default and left out of product grids.

metadataobject

Your own key-value data, up to 16 KB as JSON. Sending metadata replaces the stored object.

Returns

201 Created with the product object when the product is new, or 200 OK when an existing product was updated. Returns 422 when a field is invalid.

POST/products
Terminal
curl -X POST https://api.emailit.com/v2/products \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "8123456789",
    "title": "Trail running shoe",
    "sku": "TRS-BLU-42",
    "url": "https://shop.example.com/products/trail-running-shoe",
    "image_url": "https://shop.example.com/images/trail-running-shoe.jpg",
    "price": 89,
    "compare_at_price": 119,
    "currency": "USD",
    "categories": ["Shoes", "Running"],
    "brand": "Acme Outdoors",
    "inventory_quantity": 34
  }'
JSON
{
  "object": "product",
  "id": "prd_3r6HHUGUSl8yjYDscEA6aYA8wrA",
  "external_id": "8123456789",
  "sku": "TRS-BLU-42",
  "title": "Trail running shoe",
  "description": null,
  "url": "https://shop.example.com/products/trail-running-shoe",
  "image_url": "https://shop.example.com/images/trail-running-shoe.jpg",
  "price": 89,
  "compare_at_price": 119,
  "currency": "USD",
  "categories": [
    "Shoes",
    "Running"
  ],
  "brand": "Acme Outdoors",
  "inventory_quantity": 34,
  "status": "active",
  "metadata": {},
  "created_at": "2026-10-08T14:21:07.512Z",
  "updated_at": "2026-10-08T14:21:07.512Z"
}

Retrieve a product

Retrieve a product by its Emailit ID or by the product ID in your shop. Requires an API key with the full scope.

GET/products/{id}

Path Parameters

idstringRequired

The product ID (prd_...) or the product ID in your shop (external_id). URL-encode shop IDs that contain special characters.

The product object

objectstring

Always product.

idstring

Emailit product ID (prd_...).

external_idstring

The product ID in your shop: the id you sent. Order and cart items refer to products by this ID.

skustring | null

Stock keeping unit.

titlestring

Product name.

descriptionstring | null

Product description.

urlstring | null

Product page in your shop.

image_urlstring | null

Product image.

pricenumber | null

Current price.

compare_at_pricenumber | null

Price before a discount. A product is on sale when compare_at_price is higher than price.

currencystring | null

Three-letter ISO 4217 code of the prices.

categoriesstring[]

Category names.

brandstring | null

Brand name.

inventory_quantityinteger | null

Units in stock. null means stock isn’t tracked. Product grids in emails leave out products at 0.

statusstring

active or archived. Product grids in emails leave out archived products.

metadataobject

Your own key-value data.

created_atstring

When the product was added, in ISO 8601 UTC.

updated_atstring

When the product last changed, in ISO 8601 UTC.

GET/products/{id}
Terminal
curl https://api.emailit.com/v2/products/prd_3r6HHUGUSl8yjYDscEA6aYA8wrA \
  -H "Authorization: Bearer your_api_key"
JSON
{
  "object": "product",
  "id": "prd_3r6HHUGUSl8yjYDscEA6aYA8wrA",
  "external_id": "8123456789",
  "sku": "TRS-BLU-42",
  "title": "Trail running shoe",
  "description": "Lightweight shoe with a grippy sole for wet trails.",
  "url": "https://shop.example.com/products/trail-running-shoe",
  "image_url": "https://shop.example.com/images/trail-running-shoe.jpg",
  "price": 89,
  "compare_at_price": 119,
  "currency": "USD",
  "categories": [
    "Shoes",
    "Running"
  ],
  "brand": "Acme Outdoors",
  "inventory_quantity": 34,
  "status": "active",
  "metadata": {
    "color": "blue"
  },
  "created_at": "2026-10-02T08:15:22.418Z",
  "updated_at": "2026-10-08T14:21:07.512Z"
}

Update a product

Update a product that’s already in your catalog. Only the fields you send change. The product ID in your shop can’t change: an id in the body is ignored. Requires an API key with the full or events scope. With an events key, the response holds only object, id and external_id.

To create products and update them with the same call, use Create or update a product.

POST/products/{id}

Path Parameters

idstringRequired

The product ID (prd_...) or the product ID in your shop.

Request Body

Any of the fields of Create or update a product except id: title, sku, description, url, image_url, price, compare_at_price, currency, categories, brand, inventory_quantity, status and metadata. The same rules apply. categories and metadata are replaced as a whole.

Returns

200 OK with the updated product object. Returns 404 if no product matches id and 422 when a field is invalid.

POST/products/{id}
Terminal
curl -X POST https://api.emailit.com/v2/products/8123456789 \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "price": 79, "inventory_quantity": 20 }'
JSON
{
  "object": "product",
  "id": "prd_3r6HHUGUSl8yjYDscEA6aYA8wrA",
  "external_id": "8123456789",
  "sku": "TRS-BLU-42",
  "title": "Trail running shoe",
  "description": "Lightweight shoe with a grippy sole for wet trails.",
  "url": "https://shop.example.com/products/trail-running-shoe",
  "image_url": "https://shop.example.com/images/trail-running-shoe.jpg",
  "price": 79,
  "compare_at_price": 119,
  "currency": "USD",
  "categories": [
    "Shoes",
    "Running"
  ],
  "brand": "Acme Outdoors",
  "inventory_quantity": 20,
  "status": "active",
  "metadata": {
    "color": "blue"
  },
  "created_at": "2026-10-02T08:15:22.418Z",
  "updated_at": "2026-10-09T10:02:41.205Z"
}

List products

List the products in your catalog, newest first. Without status, only active products are listed. Requires an API key with the full scope.

GET/products

Query Parameters

pageinteger

Page number for pagination (minimum: 1, default: 1).

limitinteger

Number of products to return (minimum: 1, maximum: 100, default: 25).

searchstring

Case-insensitive match on the title, the product ID in your shop (external_id) or the SKU.

categorystring

Only products in this category. The name must match exactly, including case.

statusstring

active (default), archived or all. Use all when you filter on the status key below, because the default already limits the list to active products.

idsstring

Comma-separated list of up to 100 product IDs. Each one can be the Emailit ID (prd_...) or the product ID in your shop.

matchstring

all (default) requires every key.condition filter to match. or matches any of them. See Filtering.

sortstring

Sort key: created_at (default), updated_at, title or price.

orderstring

Sort direction: asc or desc (default).

Filters

List filters are one layer of key.condition=value query parameters. See Filtering for match, order, direction and the condition list per type.

Filter keys

KeyTypeConditionsNotes
titlestringexact, not_exact, contains, not_contains, starts_with, ends_with, empty, not_empty
external_idstringexact, not_exact, contains, not_contains, starts_with, ends_with, empty, not_empty
skustringexact, not_exact, contains, not_contains, starts_with, ends_with, empty, not_empty
brandstringexact, not_exact, contains, not_contains, starts_with, ends_with, empty, not_empty
currencystringexact, not_exact, contains, not_contains, starts_with, ends_with, empty, not_empty
pricenumberexact, not_exact, gt, gte, lt, lte, empty, not_empty
inventory_quantitynumberexact, not_exact, gt, gte, lt, lte, empty, not_empty
statusenumexact, not_exactValues: active, archived
created_atdateexact, before, after, empty, not_empty
updated_atdateexact, before, after, empty, not_empty

Sort keys

This endpoint sorts with sort set to one of these keys and order set to asc or desc (order=<key> returns 400 here): created_at, updated_at, title, price

On this endpoint, order only accepts asc or desc. Pass the sort key in sort, for example sort=price&order=asc.

Returns

A page of product objects in data, with total_records, next_page_url and previous_page_url. The page URLs carry only page and limit, so add your search and filters again when you follow them.

GET/products
Terminal
curl "https://api.emailit.com/v2/products?category=Running&sort=price&order=asc&limit=25" \
  -H "Authorization: Bearer your_api_key"
JSON
{
  "data": [
    {
      "object": "product",
      "id": "prd_3r6HHUGUSl8yjYDscEA6aYA8wrA",
      "external_id": "8123456789",
      "sku": "TRS-BLU-42",
      "title": "Trail running shoe",
      "description": "Lightweight shoe with a grippy sole for wet trails.",
      "url": "https://shop.example.com/products/trail-running-shoe",
      "image_url": "https://shop.example.com/images/trail-running-shoe.jpg",
      "price": 89,
      "compare_at_price": 119,
      "currency": "USD",
      "categories": [
        "Shoes",
        "Running"
      ],
      "brand": "Acme Outdoors",
      "inventory_quantity": 34,
      "status": "active",
      "metadata": {
        "color": "blue"
      },
      "created_at": "2026-10-02T08:15:22.418Z",
      "updated_at": "2026-10-08T14:21:07.512Z"
    }
  ],
  "total_records": 1,
  "next_page_url": null,
  "previous_page_url": null
}

Create or update products in bulk

Send up to 1,000 products in one request, for example to import your catalog or to sync it on a schedule. Each product follows the rules of Create or update a product: it’s created or updated by its id, a new product needs a title, and fields are written only when you send them. Requires an API key with the full or events scope. With an events key, the response holds only object, id and external_id.

Invalid products are skipped and listed in rejected; the others are stored. The request still returns 200.

POST/products/batch

Request Body

productsobject[]Required

1 to 1,000 products, each with the fields of Create or update a product.

Returns

createdinteger

Number of new products.

updatedinteger

Number of existing products that were updated.

rejectedobject[]

Products that weren’t stored. Each item has the index of the product in your products array and errors, keyed by field path such as products.3.price.

Returns 422 if products is empty or has more than 1,000 items.

POST/products/batch
Terminal
curl -X POST https://api.emailit.com/v2/products/batch \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "products": [
      { "id": "8123456789", "title": "Trail running shoe", "price": 89, "currency": "USD", "categories": ["Shoes", "Running"] },
      { "id": "8123456790", "title": "Merino running socks", "price": 18, "currency": "USD", "categories": ["Accessories"] },
      { "id": "8123456791", "price": 49, "currency": "USD" }
    ]
  }'
JSON
{
  "created": 1,
  "updated": 1,
  "rejected": [
    {
      "index": 2,
      "errors": {
        "products.2.title": [
          "is required"
        ]
      }
    }
  ]
}

List product categories

List the categories used by active products, in alphabetical order, with the number of active products in each. Archived products aren’t counted. Returns up to 1,000 categories and isn’t paginated. Requires an API key with the full scope.

Categories come from the categories of each product. Use a category name with the category parameter of List products.

GET/products/categories
GET/products/categories
Terminal
curl https://api.emailit.com/v2/products/categories \
  -H "Authorization: Bearer your_api_key"
JSON
{
  "data": [
    {
      "name": "Accessories",
      "products": 18
    },
    {
      "name": "Running",
      "products": 12
    },
    {
      "name": "Shoes",
      "products": 27
    }
  ]
}

Delete a product

Remove a product from your catalog. Orders that contain it keep their items, which store their own title, price and product ID. To hide a product without deleting it, set its status to archived instead. Requires an API key with the full scope.

If the tracking script reports a view of a deleted product with its title, the product is added to the catalog again from the page data.

DELETE/products/{id}

Path Parameters

idstringRequired

The product ID (prd_...) or the product ID in your shop.

DELETE/products/{id}
Terminal
curl -X DELETE https://api.emailit.com/v2/products/prd_3r6HHUGUSl8yjYDscEA6aYA8wrA \
  -H "Authorization: Bearer your_api_key"
JSON
{
  "object": "product",
  "id": "prd_3r6HHUGUSl8yjYDscEA6aYA8wrA",
  "deleted": true
}

Was this page helpful?

Thanks for the feedback.

Thanks, we read every message.