Changelog
Changes to the public atouch API (/v1) contract, newest first. Backward-compatible additions such as new response fields ship without notice, as described in Versioning & deprecation. This page is where you can see what shipped.
- AddedNew fields or endpoints
- ChangedBehavior change (backward compatible)
- FixedBug fix
- DocsBehavior unchanged
2026-10-22
The 429 response is now declared on every endpoint, and required headers and token-endpoint behavior are documented.
429 (rate limited) declared on every endpoint
The spec (OpenAPI) did not declare 429, so generated SDKs treated it as an unexpected response. Behavior is unchanged: on 429, retry after Retry-After (seconds).
413 (payload too large) declared on endpoints that take a request body
Request bodies over 1 MiB return 413 (payload_too_large). Normal use does not come close to this size.
The User-Agent header is required
Requests without a User-Agent are rejected with 403 (HTML body) before they reach the API. This was already the behavior but was not documented. Send something like your-integration/1.0 (+https://example.com/contact).
Token endpoint no longer distinguishes authentication failure reasons
Unknown client_id, disabled clients, and wrong client_secret all return the same 401 (invalid_client, client authentication failed). Repeated failures in a short time return 429 (rate_limited); retry after Retry-After. code_verifier must be 43-128 unreserved characters (A-Z a-z 0-9 - . _ ~).
Access tokens can be revoked at /v1/oauth/revoke
Pass an access token (JWT) as token (token_type_hint=access_token) to revoke just that token before it expires. Environments that do not offer this return 400 (unsupported_token_type). Refresh-token revocation is unchanged.
2026-10-09
Added read fields for stock and orders. Existing fields keep their values and types.
Check your integration if you set stock with an absolute value (inventory). inventory is the count after stock held by checkouts in progress has been deducted. Sending your total on hand as-is overstates stock by the held amount. To match a total, send the difference from the total you read as adjustment.
Items now return stock held by checkouts in progress
Stock is deducted as soon as a buyer starts paying. reserved_inventory returns that amount. Your total on hand is inventory + reserved_inventory.
| Field | Type | Description |
|---|---|---|
+ reserved_inventory | integer | null | Stock held by checkouts in progress. null when inventory is null. The key is omitted when the value could not be read |
+ variants[].reserved_inventory | integer | null | Held stock per variant. Returned by the item detail |
{ "id": "1487", "inventory": 9,+ "reserved_inventory": 1, "variants": [ { "id": "2", "inventory": 4,+ "reserved_inventory": 0 } ] }
Order line items now return the purchased variant
A line item's sku is the SKU currently set on the parent item. Use variant to identify what was bought.
| Field | Type | Description |
|---|---|---|
+ variant | object | null | The purchased variant. null for items without variants. The key is omitted when the value could not be read |
+ variant.id | string | null | ID of the matching current variant. null when it cannot be determined |
+ variant.sku | string | null | The variant's SKU at the time of purchase |
+ variant.name | string | The variant's name at the time of purchase |
{ "sku": "TS-001",+ "variant": {+ "id": "2",+ "sku": "TS-001-WH-M",+ "name": "白 / M"+ } }
Shipments now return when the tracking was registered and its delivery date
| Field | Type | Description |
|---|---|---|
+ tracking_registered_at | date-time | null | When the tracking was registered (UTC). null does not mean the order has not shipped |
+ tracking_delivery_date | date | null | The delivery date registered on the tracking. Not the same as the buyer's requested date (delivery_date) |
{ "delivery_date": "2026-10-04", "tracking_number": "1234-5678-9012",+ "tracking_registered_at": "2026-10-01T03:00:00.000Z",+ "tracking_delivery_date": "2026-10-03" }
Clearer descriptions for stock, line items, shipments and order status
| Subject | Before | After |
|---|---|---|
inventory | Current stock | Current stock, after deducting stock held by checkouts in progress |
inventory in a stock update | Sets an absolute value | Sets an absolute value, overwriting as given. Do not send your total on hand as-is |
sku on a line item | Product code | The SKU currently set on the parent item, not the value at the time of purchase |
tracking_number | Tracking number | Tracking number. When there are several, the first one registered |
| Order status | Meaning of each value | Also notes that reward-exchange orders can be no_shipping from creation |
Tracking numbers registered or corrected through the API, and shipping statuses changed through the API, now keep correct timestamps.
Tracking numbers registered through the API now have a registration time
Until now, tracking numbers registered through the API had no registration time, so tracking_registered_at was null. They are now recorded the same way as in the admin console. Tracking numbers registered through the API before this change stay null.
Orders whose shipping status was changed through the API now appear in incremental fetches
Until now, changing the shipping status through the API did not advance the order's update time, so the order did not appear when fetching with updated_since. The update time now advances the same way as in the admin console. If you fetch incrementally, changed orders appear again, so de-duplicate by order ID.
Fixed delivery dates returned one day early when correcting tracking numbers
When a correction omitted delivery_date, the response returned the date one day early. Sending the same delivery date was also recorded as a correction.
Stock updates can now take your total on hand as-is.
Stock updates accept a total
Send your total on hand (sellable stock plus stock held by checkouts in progress) as total_inventory, and the API deducts the held amount before saving. It cannot be combined with inventory or adjustment.
| Field | Type | Description |
|---|---|---|
+ total_inventory | integer | Request. Total stock (0–99999). Items without managed stock return 422 (unlimited_inventory) |
+ expected_total_inventory | integer | Request. The total you read. Only valid together with total_inventory. If it differs from the current total, nothing is written and 409 (total_inventory_changed) is returned |
+ reserved_inventory | integer | Response. Returned only when total_inventory was sent. The held amount counted during the update |
# 読み取った値: inventory 9、reserved_inventory 1(総数 10)。倉庫を数えたら 12 だった- { "adjustment": 2 }+ { "total_inventory": 12, "expected_total_inventory": 10 }
Two new 409 error codes for stock updates
Both are returned only when total_inventory was sent, and nothing was written. They need different handling, so branch on the code.
| Field | Type | Description |
|---|---|---|
+ inventory_busy | 409 | The stock row was in use (for example, by a checkout in progress). Resend after Retry-After with the same Idempotency-Key |
+ total_inventory_changed | 409 | The total changed after you read it. Read the item and orders again, recalculate, and send with a new Idempotency-Key |
2026-09-25
503 responses are now split into ones you can retry and ones retrying will not fix.
503 now uses two error codes
A capability that is not offered in the environment returns capability_not_enabled; retrying will not succeed. Temporary failures still return service_unavailable, now with a Retry-After header.
| Subject | Before | After |
|---|---|---|
| Capability not offered | service_unavailable | capability_not_enabled (no Retry-After; do not retry) |
| Temporary failure | service_unavailable | service_unavailable (with Retry-After; wait that long, then retry) |
HTTP/1.1 503 Service Unavailable { "error": {- "code": "service_unavailable",+ "code": "capability_not_enabled", "message": "…" } }
2026-09-24
Fixed a bug that made item creation fail.
Item creation no longer returns 500
Requests that created an item returned 500 (internal_error). The request and response shapes are unchanged.
2026-08-29
The item list now returns the sales period, and date-time inputs accept values with an offset.
Sales period added to the item list
status: active means the item is published, not that it can be bought. Items outside their sales period cannot be purchased. The item detail already returned these fields.
| Field | Type | Description |
|---|---|---|
+ sell_from | date-time | null | Start of the sales period |
+ sell_by | date-time | null | End of the sales period. Items past this time cannot be purchased |
{ "id": "1487", "status": "active",+ "sell_from": "2026-08-01T00:00:00.000Z",+ "sell_by": "2026-08-31T14:59:59.000Z" }
Date-time inputs accept values with an offset
Applies to date-time inputs such as the sales period (sell_from / sell_by). You can now write back the UTC value a response returned. The previous format still works.
| Subject | Before | After |
|---|---|---|
2026-08-25 00:00:00 | Accepted | Accepted |
2026-08-24T15:00:00.000Z | 400 | Accepted |
Item status values are now described
The spec now states that active means published, not purchasable.
Validation errors (400) now say which fields are invalid.
Validation errors (400) list the invalid fields
| Field | Type | Description |
|---|---|---|
+ error.issues[] | array | Present only on validation errors (400). Lists each invalid field (path) with an explanation (message). The wording of message is not guaranteed |
{ "error": { "code": "invalid_request", "message": "…",+ "issues": [+ { "path": "limit", "message": "…" }+ ] } }
Variant responses now document item_id
The field was already in the response but missing from the spec.
2026-08-26
Date and time fields now declare a format in the spec.
Date and time fields now declare a format
The spec now declares date-time for timestamps and date for dates in responses (with a few exceptions). Response values are unchanged.
Fixed a bug that made tracking updates fail.
Tracking updates no longer return 500
Requests that corrected a tracking number always returned 500. The request and response shapes are unchanged.
2026-08-25
The atouch API (/v1) is now available.