API documentation

How it works

  1. Sign up and copy the key. It is shown only once.
  2. Wait until EJS approves the company.
  3. Call the catalog from your server with that key.

The catalog is read-only and is called from the reseller’s server. Each request sends the company key in the X-Api-Key header. Until the account is approved, the key returns 403 pending_approval.

Base: https://n8n.ejscomputers.com/webhook/v1. Allowed method: GET.

Endpoints

  • GET /products — catalog list
  • GET /products/{sku} — one product
  • GET /categories — categories

Parameters for /products

Parameter Role
category Category slug
sku Up to 50 SKUs, separated by commas
include_out_of_stock Include out-of-stock items. Default: false
updated_since ISO 8601 date. Products changed since this date
limit 1 to 200. Default: 50
cursor Next page, using next_cursor

Response

data holds the products. pagination gives limit, next_cursor, and total. meta gives api_version, request_id, and generated_at. An error looks like { "error": { "code", "message", "parameter?" }, "meta" }.

Product

Fields: sku, title, condition (new or used), category (slug, name_fr, name_en), brand, mpn, upc, quantity, in_stock, price, discount_price, discount_ends_at, currency (CAD), weight_kg, images (url, alt, position), image_missing, attributes (value, unit, label_fr, label_en), updated_at, variants.

The top-level price is the product alone.

Cable variant

variants is a list of objects { variant, sku, price, discount_price, in_stock, quantity, includes? }. variant is base or cable. SATA HDDs and SSDs have a cable variant: the SKU ends in -CABLE and a SATA cable is included.

Sync

  1. Run a full pass with include_out_of_stock=true.
  2. Keep the greatest updated_at received.
  3. Follow next_cursor until it is null.
  4. On later passes, call updated_since with that updated_at, again until next_cursor is null.

Error codes

  • 400 — invalid parameter
  • 401 — missing or rejected key
  • 403 — forbidden or pending_approval
  • 404 — not found
  • 405 — method other than GET
  • 429 — limit reached. The Retry-After header gives the delay
  • 502 — upstream error

curl example

curl -s "https://n8n.ejscomputers.com/webhook/v1/products?limit=50&include_out_of_stock=true" \
  -H "Accept: application/json" \
  -H "X-Api-Key: ejs_VOTRE_CLE"
curl -s "https://n8n.ejscomputers.com/webhook/v1/products/HDD-EXEMPLE-2TO" \
  -H "X-Api-Key: ejs_VOTRE_CLE"
curl -s "https://n8n.ejscomputers.com/webhook/v1/categories" \
  -H "X-Api-Key: ejs_VOTRE_CLE"

Example response

{
  "data": [
    {
      "sku": "HDD-EXEMPLE-2TO",
      "title": "Disque dur 2 To",
      "condition": "used",
      "category": { "slug": "hdd", "name_fr": "Disques durs", "name_en": "Hard drives" },
      "brand": "Exemple",
      "mpn": "EX-2TB",
      "upc": "000000000000",
      "quantity": 4,
      "in_stock": true,
      "price": "49.00",
      "discount_price": null,
      "discount_ends_at": null,
      "currency": "CAD",
      "weight_kg": 0.42,
      "images": [{ "url": "https://exemple.invalid/hdd.jpg", "alt": "Disque dur", "position": 1 }],
      "image_missing": false,
      "attributes": {
        "capacity": { "value": "2", "unit": "TB", "label_fr": "Capacité", "label_en": "Capacity" }
      },
      "updated_at": "2026-10-08T12:00:00Z",
      "variants": [
        {
          "variant": "base",
          "sku": "HDD-EXEMPLE-2TO",
          "price": "49.00",
          "discount_price": null,
          "in_stock": true,
          "quantity": 4
        },
        {
          "variant": "cable",
          "sku": "HDD-EXEMPLE-2TO-CABLE",
          "price": "54.00",
          "discount_price": null,
          "in_stock": true,
          "quantity": 4,
          "includes": "Câble SATA"
        }
      ]
    }
  ],
  "pagination": { "limit": 50, "next_cursor": null, "total": 1 },
  "meta": {
    "api_version": "v1",
    "request_id": "req_exemple",
    "generated_at": "2026-10-08T12:00:01Z"
  }
}

Example error

{
  "error": {
    "code": "invalid_parameter",
    "message": "limit must be between 1 and 200",
    "parameter": "limit"
  },
  "meta": {
    "api_version": "v1",
    "request_id": "req_exemple",
    "generated_at": "2026-10-08T12:00:01Z"
  }
}