Skip to main content
This guide gathers the operational rules to design a reliable integration: how many requests you can send, what happens when analyses queue up, how to retry safely, and how to recover when a response or a webhook never reaches you.

Rate limits

Limits apply to every Partner API endpoint, including POST /analysis/start and the polling endpoint GET /analysis/{analysis_id}/results. There is no separate budget for starting analyses and polling results. The limits are throttling, not banning: when you exceed them, requests are slowed down or rejected with 429 Too Many Requests for a short time, then traffic flows again as soon as your request rate drops back under the limit. Your key is never blocked or revoked because of it.
The IP limit is shared by every key calling from the same address. If several of your services or stores egress through one NAT or proxy IP, they share the 500 requests per minute.

Budget your polling

Polling is usually what consumes the 100 requests per minute. Each analysis polled every 5 seconds uses 12 requests per minute, so a single key can poll roughly 8 analyses in parallel before being throttled. If you run several stores or many concurrent analyses on one key:
  • Use webhooks as the primary signal and poll only as a fallback, at a slow interval (for example every 30 seconds for analyses that have not reached a terminal event).
  • Use a single poller per API key that schedules all analyses, rather than one poller per store, so you can enforce your own budget.
  • Do not poll GET /analysis (the list endpoint) to track progress. It returns every analysis in one unpaginated response, without timestamps.
  • Back off when you receive 429 or 5xx (see retry guidelines).

Concurrency and pending analyses

There is no per-account cap on the number of analyses processed concurrently or waiting in pending. Ochy does not reject a start request because other analyses are in progress: a valid POST /analysis/start is always accepted with 202 and a video_id, and waits its turn in pending if needed. An accepted analysis moves through the statuses described in the analysis workflow. While capacity is busy it stays pending; it then becomes analyzing, and ends as success or failed. The only business reasons for a start request to be refused are validation errors (400, 413) and an empty balance (424 insufficient_api_credits).

How long can an analysis take?

Most analyses complete within 10 to 30 seconds. If an analysis does not reach a terminal state (success or failed) within 30 minutes of being accepted, Ochy marks it as failed and automatically refunds the credit. The check runs hourly, so the failed status can appear up to about 90 minutes after the start.
We recommend investigating an analysis that is still pending after about 5 minutes, or whose percentage has not moved for about 5 minutes while analyzing. There is no need to resubmit it: it will either complete or be failed and refunded automatically. Resubmitting creates a new analysis and consumes another credit.

Safe retries with Idempotency-Key

If you do not receive the response of POST /analysis/start (timeout, dropped connection), you cannot know whether the analysis was created. Send an Idempotency-Key header with every start request so you can retry without creating a duplicate or consuming another credit.
Generate the key once per logical submission (for example when you create the job in your own database), store it with the job, and reuse it for every retry of that job.

Recovering a lost video_id

1

Retry with the same Idempotency-Key (recommended)

Send the same request again with the same Idempotency-Key. You get back the original video_id whether or not the first request had reached us. This works the same for polling and webhook integrations: once you hold the video_id, you can poll it or match its webhook events.
2

Look the analysis up by subject (fallback)

If you attached a subject_id, GET /analysis/subjects/{subject_id} lists the analyses linked to that subject with their id and status.
3

List your analyses (last resort)

GET /analysis returns id, analysis_type, status and subject_id for every analysis. It has no creation time and no client reference, so it cannot identify one specific request on its own.
Webhook events carry only the analysis_id (the same value as video_id). They do not include any client-side reference. If you never received the video_id, you cannot match an incoming event to a request: recover the video_id with an idempotent retry first.

Webhook delivery guarantees

Each webhook event is delivered at most once: Ochy makes a single attempt with a 10-second timeout. There is no automatic retry if your endpoint is down, times out, or answers with a non-2xx status. This is deliberate. Progress events are only valuable when they arrive on time: a progress update delivered several seconds late is already outdated. A retry policy would also mean repeatedly calling an endpoint that may have been misconfigured, for example a wrong URL. What this means for your integration:
  • Treat webhooks as a fast notification, not as a guaranteed log.
  • Keep a fallback poll for every analysis that has not reached a terminal event (analysis.completed or analysis.failed), at a slow interval such as 30 seconds, and within your rate limit budget.
  • Order and deduplicate with the per-analysis sequence. Missing sequence numbers are expected; only the terminal state matters.
  • Respond with 2xx quickly and process the payload in the background.
  • Use GET /analysis/{analysis_id}/results as the single source of truth after any delivery issue.

Retry guidelines

Use exponential backoff with jitter, for example 2 s, 4 s, 8 s, up to a ceiling of about 60 s, and stop after a bounded number of attempts. Ochy does not send a Retry-After header, so rely on your own backoff.