Public intake API

APIHelp and docs

Submit data to staging with an intake key. This API does not publish directly to live data and does not use your tenant's read or write key.

1. Get an intake key

A Stockisto operator issues a key with api:intake, bound to your tenant and one source: scraper, delegated or crowd. Send it in X-API-Key. Keep it in a server-side secret store; it is shown once. Keys with api:read or api:write cannot use intake, and an intake key cannot read the tenant API.

The envelope's source and any provenance.source on a record must match the key's binding. Expired, revoked and unknown keys return 401.

2. Submit a batch

Replace the placeholders and use the source bound to your key. This request writes to staging; run it only with a key issued for your source.

curl -X POST https://api.test.stockisto.com/api/public/v1/intake/batches \
  -H "X-API-Key: <YOUR_INTAKE_KEY>" \
  -H "Content-Type: application/json" \
  --data '{"contractVersion":"1.0","source":"scraper","idempotencyKey":"<UNIQUE_BATCH_KEY>","records":[{"kind":"retailer-company","naturalKey":"<UNIQUE_RETAILER_KEY>","payload":{"name":"<RETAILER_NAME>"}}]}'

A new batch returns 202 with its id, status and a Location status link. Repeating the same idempotencyKey with the submitting key returns 200 and the existing batch with duplicate: true. It adds no volume, even when your daily quota is exhausted. The key is unique within the tenant; a collision with another credential returns 409.

FieldRule
contractVersionRequired: 1.0.
sourceRequired: the key's bound source.
idempotencyKeyRequired, at most 200 characters.
descriptionOptional, at most 500 characters.
metadataOptional JSON object.
recordsFrom 1 to 50,000 records.
kindRequired; supplier-company, retailer-company, installer-company and retailer-stock have appliers. Other valid kinds stay staged.
naturalKeyRequired for those four kinds; at most 512 characters.
payloadRequired JSON object; at most 256 KB.
provenanceOptional source, fetchedAt (UTC, no future time), confidence (0 to 1) and sourceRef (at most 1024 characters).

Read validationErrors for rejected records. Valid records continue; an invalid envelope or a batch with no valid records is refused.

3. Read status and review

GET /api/public/v1/intake/batches lists only batches submitted by this key. Use GET /api/public/v1/intake/batches/<BATCH_ID> for one batch. Another key's batch returns 404, including within the same tenant.

Statuses are received, validated, staged, in_review, applied, partially_applied and rejected. Source batches stop at in_review unless an operator has granted source trust for auto-apply. An unusually large removal always requires review. Check the status to confirm application; acceptance alone does not mean publication.

An operator can register an HTTPS callback URL on the key. Terminal states applied, partially_applied and rejected trigger a signed import.completed delivery.

4. Limits

LimitValue
Request body64 MB
Records per batch50,000
Record payload256 KB
Requests per key30 per minute
Batches per UTC day200 by default; up to 10,000 at issuance
Records per UTC day500,000 by default; up to 10,000,000 at issuance

A daily refusal returns 429, error: "intake_quota_exceeded" and a quota object with dailyBatchLimit, batchesToday, dailyRecordLimit, recordsToday and resetAt. Honour Retry-After; resume after the reset instead of repeatedly resubmitting.

5. Recover from a refusal

StatusNext step
400Correct the fields listed in errors.
401Ask the operator to issue or rotate the key.
403Match the bound source and use an api:intake key.
404Read the batch with its submitting key.
409Choose a new idempotencyKey; another credential owns it.
413Split the batch into smaller requests.
429Wait for Retry-After or the daily resetAt.

For tenant imports, use the Public imports API instead.

For retailer file feeds, see Retailer feeds.