Monitor and Recover Gaming Inventory Uploads
Gaming Inventory processing is asynchronous. Customer integrations are responsible for discovering the trace created by every upload, polling it to a terminal status, and recovering safely when processing fails.
Non-negotiable monitoring rules
For every brand:
- Permit only one upload at a time.
- Record the UTC upload time, source version, file checksum, and game count.
- Discover the processing trace through
GET /logs/recent. - Store the trace ID in your own durable run record.
- Poll
GET /logs/trace/{traceId}with backoff. - Treat
COMPLETEDas terminal technical completion, then reconcile the exported game-code set. - Alert and stop later uploads when the result is
FAILED, remains non-terminal beyond your agreed processing window, or fails reconciliation.
Do not infer success from:
- HTTP
200from/validate; - a successful upload-form response;
- a successful file-transfer status;
- the presence of a trace; or
- completed individual steps while the main log is still non-terminal.
Find recent traces
curl --silent --show-error --fail-with-body \
--request GET \
--url 'https://api.opti-x.optimove.net/inventory/v1/logs/recent' \
--header 'x-api-key: {{service_api_key}}' \
--header 'x-brand-key: {{brand_key}}'The implementation queries traces for the authorised brand from up to the previous 24 hours, most recent first. It stops after approximately 1,000 raw main-and-step items, so busy brands can receive only a subset:
{
"traces": [
{
"traceId": "example-version-id",
"mainLog": {
"traceId": "example-version-id",
"recordType": "MAIN",
"brandKey": "123",
"fileName": "brand/123/inventory/games.json",
"fileSize": 4281,
"status": "STARTED",
"timestamp": "2026-01-01T12:00:05+00:00"
},
"steps": []
}
],
"count": 1,
"total_items": 1,
"filtered_incomplete": 0
}The trace may not appear immediately after the file upload. Retry with bounded exponential backoff—for example, after 2, 5, 10, 20 and then 30 seconds—without starting another upload.
Identify a trace using the recorded upload time and the fact that no other upload for that brand is allowed to overlap. Persist its traceId; recent logs are a discovery aid, not a durable audit store.
Read one trace
curl --silent --show-error --fail-with-body \
--request GET \
--url 'https://api.opti-x.optimove.net/inventory/v1/logs/trace/{{trace_id}}' \
--header 'x-api-key: {{service_api_key}}' \
--header 'x-brand-key: {{brand_key}}'The response has two parts:
mainLogis the authoritative overall result.stepsshow the stages that started, completed or failed and can help diagnose an error.
Important main-log fields:
| Field | Meaning |
|---|---|
traceId | Unique identifier for this processing run. Treat it as an opaque string, capture it, and retain it for support diagnostics |
timestamp | UTC time at which processing was logged |
brandKey | Brand whose catalogue was processed |
fileName | Uploaded file name |
fileSize | Uploaded size in bytes |
status | Overall processing status |
processedRows | 0 when no common-inventory change was detected; otherwise the full post-difference inventory row count returned by the processor. It is not a create/update delta. |
duration | Processing duration in milliseconds |
errorMessage | Overall failure detail when status is FAILED |
Status handling
| Main status | Terminal? | Integration behaviour |
|---|---|---|
STARTED | No | Continue polling; keep the per-brand upload lock |
COMPLETED | Yes | Record technical completion, then reconcile the exported Inventory view before marking the run successful or releasing the upload lock |
FAILED | Yes | Mark the run failed, alert and keep automated later uploads blocked until recovery is approved |
Step records can use STARTED, COMPLETED and FAILED. A failed step normally identifies where processing stopped, but the terminal processing decision must use mainLog.status. Business success additionally requires reconciliation.
Reconcile the exported inventory view
A COMPLETED trace means the processor returned without an exception. It does not guarantee that a large removal was applied consistently: current safety controls can suppress part of a deletion of more than half the catalogue while the trace still completes.
After every completed run:
- Confirm
stepMetadata.inventory_rowson the completedGET_DATAstep equals the submitted root-object game count. This proves the processor read the expected file. - After the normal downstream propagation period agreed during onboarding, call
GET /download. - Decompress the CSV and compare its
game_codecount and set with the intended snapshot. - When that exported view matches, mark the customer-side reconciliation complete and release the per-brand upload lock.
- Continue monitoring event-to-inventory joins and representative recommendation results; no public endpoint currently confirms that your full inventory is being served.
- If the export does not match within the agreed window, alert, block later uploads and provide both code sets and the trace ID to Optimove support.
curl --silent --show-error --fail-with-body \
--request GET \
--url 'https://api.opti-x.optimove.net/inventory/v1/download' \
--header 'x-api-key: {{service_api_key}}' \
--header 'x-brand-key: {{brand_key}}' \
--output processed-inventory.csv.gzThe export is a processed, replicated view and can lag the trace. It is useful for game-code reconciliation, but it is not a lossless copy of every submitted field, has no public immediate-consistency guarantee, and cannot prove cross-store atomicity. Keep your submitted snapshot as the source of truth. Never send a snapshot removing more than half the catalogue through the normal flow; coordinate that operation with Optimove.
Trace logs have finite platform retention and are not your audit store. Keep your own run record and exact submitted file for the period required by your organisation.
Recommended run record
Store at least:
{
"brand_key": "123",
"source_version": "catalogue-2026-01-01T12:00:00Z",
"upload_started_at": "2026-01-01T12:00:00Z",
"file_sha256": "example-sha256",
"submitted_game_count": 120,
"trace_id": "example-version-id",
"status": "COMPLETED",
"processed_rows": 120,
"export_reconciliation_status": "MATCHED",
"exported_game_count": 120,
"processing_duration_ms": 6842,
"monitoring_completed_at": "2026-01-01T12:00:12Z"
}When present, compare stepMetadata.inventory_rows on the completed GET_DATA step with your submitted game count. Interpret processedRows using the table above; do not treat it as a change count.
Request a submitted version for a trace
Use the trace download endpoint when you need to attempt retrieval of the file version associated with a run:
curl --silent --show-error \
--request GET \
--url 'https://api.opti-x.optimove.net/inventory/v1/logs/trace/{{trace_id}}/download' \
--header 'x-api-key: {{service_api_key}}' \
--header 'x-brand-key: {{brand_key}}' \
--dump-header trace-download-headers.txt \
--output trace-download-response.jsonFor an authorised trace record, the API returns HTTP 302 with a temporary URL in the Location header. That URL is valid for one hour. Fetch it in a second request without forwarding the Gaming Inventory API credentials to that URL.
Treat download as best-effort: the temporary URL can still fail on retrieval, and a stored version is not guaranteed to be available for every trace. Download diagnostics promptly and always retain your own submitted file; this endpoint is not a durable archive.
The endpoint can return:
| Status | Meaning |
|---|---|
302 | Temporary download URL created; this does not prove the storage object/version still exists |
403 | The trace belongs to another brand |
404 | Trace record not found |
500 | The download URL could not be created |
The temporary storage URL can separately return a missing-key or missing-version error.
Recovery after FAILED
FAILEDDo not retry blindly. Use this sequence:
- Keep later uploads for the brand blocked.
- Save the full trace response, including
errorMessageand allsteps. - Attempt to download the trace version; if it is unavailable, use the exact submitted file retained in your run archive.
- Compare its checksum, game count and game-code set with the run record.
- Correct the problem in your authoritative catalogue or export process.
- Generate a new complete snapshot from the current authoritative state.
- Repeat local checks and call
/validatewith the entire corrected file. - Request a new upload form and submit the corrected snapshot once.
- Capture the new trace ID and monitor it independently to
COMPLETED. - Reconcile its exported game-code count and set.
- Link the recovery trace to the failed trace in your run history.
Never upload a small patch file to repair one bad game. A later file is another complete snapshot, so a patch would make every omitted game a deletion candidate.
Recovery when no trace appears
If the temporary upload request succeeded but no new trace appears:
- Confirm the multipart file upload itself returned a successful status.
- Confirm all signed fields from
/uploadwere submitted unchanged. - Confirm the form had not expired.
- Poll
/logs/recentwith bounded backoff for the recorded brand and upload time. - Do not upload again while the first upload's state is unknown.
- If no trace appears within your agreed processing window, contact Optimove support with the brand key, UTC upload time, file checksum, upload response status and captured response headers.
Alerting recommendations
Create alerts for:
- a
FAILEDmain status; - no trace discovered within the agreed window;
- a trace remaining
STARTEDbeyond the agreed window; - a
GET_DATAinventory-row count that differs from the submitted game count; - a catalogue count drop or unexpected set of removed game codes;
- repeated validation failures; and
- an attempted overlapping upload.
See Troubleshooting for common causes and fixes.
Updated about 2 hours ago
