Skip to main content
POST
← Sold Products API Send the products your organization sells with their sales: one or more periods, each with the quantity sold in each country. Nothing is calculated, so the request is synchronous (see how bulk ingestion works): it answers 201 Created with each product and the periods the request wrote. It also records an ingest job, born completed, that sends no webhook. A product is identified by its name in the organization: a record whose name already exists adds its periods to that product. The emissions of a sold product come from the data of its use (use of sold products), not from this route.
Beta. Part of the bulk ingest API, in beta. The contract may still change before general availability.

How it works

  1. Every record is checked: its schema, the unit and countries of each period, and its periods against those the product already has. If any record is invalid the whole request is rejected with 422 and nothing is written (all or nothing): rejected is the number of invalid records and errors lists them (up to 100).
  2. The name identifies a product in the organization, case aside (Compressor X200 and compressor x200 are one product). A record whose name is new creates the product; a record whose name exists adds its periods to that product, and the answer gives the existing product’s id and stored name. Two records with the same name reject the second (DUPLICATE_PRODUCT): put all the periods of a product in one record.
  3. A period cannot overlap another of its product, the dates of both included. Within a record that is a schema error (SCHEMA_INVALID); against a period the product already has, the same period included, it is PERIOD_OVERLAPS, with the id of that period. So send every country of a period in one request: a later request cannot add countries to it. To replace a period, delete it first with Delete Period, or delete the product if it is its only period.
  4. Each country appears once in a period (DUPLICATE_SALE otherwise). Unlike the file import, two quantities of the same country are never summed silently.
  5. Everything is written in one transaction and returned, in the order sent. source_row_index is the position of the record in records, and client_row_id echoes yours. Each product comes with the periods this request wrote, with their sales; the periods it already had are left out.
  6. The products belong to the x-organization-id organization. A record cannot name another one, not even one of your perimeter: send each organization’s products with its own x-organization-id.
Nothing is calculated here: the emissions of a product come from the data of its use, sent per period with Create Use of Sold Products (v2). To retry a request safely, repeat it with the same Idempotency-Key.

Units

The unit_id of a period is one of the units of a product (GET /v2/units?type=products, see List Units). Any other is UNIT_NOT_SUPPORTED.

Request

Headers

string
required
Your API key (see Authentication).
string
required
The organization the products belong to.
string
required
1 to 255 characters, one per batch, looked up per organization across every v2 bulk route. Within 24 hours, the same key with the same route and body answers the same products (with Idempotent-Replayed: true) instead of writing them again; the same key with another body or on another route is 422 IDEMPOTENCY_KEY_REUSED, and while the first request is still being processed 409 IDEMPOTENCY_KEY_IN_PROGRESS. After 24 hours the key is free, and a request with it is a new one. See The Idempotency-Key.

Query Parameters

boolean
default:"false"
Check only: the same 422 for invalid records, nothing written; 200 with {"dry_run": true, "submitted": n, "valid": n} when every record is valid. It does not check or store the Idempotency-Key.

Body Parameters

array[object]
required
The products to create or add periods to, 1 to 1,000. A field not listed here is rejected (SCHEMA_INVALID).

Response

201 Created with items: one per record, in the order sent, with its source_row_index, client_row_id and its sold_product:
  • id: the product’s id, new or existing, the one Delete Sold Products (v2) takes and the product_id of List Sold Products.
  • organization_id, name (as stored: an existing product keeps its own spelling), created_at (when the product was created, earlier for an existing one).
  • periods: the periods this request wrote, by start_date, each with its id, start_date, end_date, unit_id and sales (id, country, quantity).

Errors

Problem details. Per-record codes in errors[].error_code of a 422 BULK_RECORDS_REJECTED: Request-level errors: 401 for a missing or invalid API key, 403 LOGGED_USER_NOT_MEMBER when the key’s user is not a member of the organization, 422 REQUEST_VALIDATION_FAILED for a malformed body (no records, more than 1,000, no Idempotency-Key), 422 IDEMPOTENCY_KEY_REUSED, 409 IDEMPOTENCY_KEY_IN_PROGRESS, and 429 beyond the rate limits.

Limits

Delete Sold Products (v2)

Delete products by id

List Sold Products

The products stored

List Periods

All the periods of a product

List Ingest Jobs

The job each request records