taskId (your tracking number), and are free to do other things. You can then either receive a delivery notification (a webhook) or check the tracking status online yourself (polling).
Our async API works the same way. You submit a task, we give you a taskId, and we process your request in the background. You can submit tasks one at a time or in batches of up to 500.
When to use async requests
This approach works well when:- Your application, especially if it’s running in a serverless environment, has short execution time limits.
- You want to submit a large number of requests quickly without waiting for each one to complete. The batch endpoint lets you submit up to 500 tasks in a single request.
- You need to build a more resilient system that isn’t dependent on a single, long-running connection.
How it works: a two-step process
The process involves two steps: making a request and then fetching the result.Step 1: make an API request
First, you send an API request. If you include awebhook.url, we’ll notify you when the job is done. If you omit it, you will need to poll for the result.
Identifying your requests with Generate unique keys using UUIDs, timestamps, or a combination of user ID + timestamp to ensure no duplicates.
idempotencyKeyYou can optionally include an idempotencyKey in your request. This is a unique string you create that allows you to easily identify and reference your requests in your own system.The idempotencyKey must be a unique string across your entire account. If you submit a request with an idempotency key that has already been used, the API will return an error:taskId.
taskId and wait for the results.
Understanding task statesEvery async task goes through four possible states:
QUEUED: The request is received and waiting its turn to be processed. Tasks are processed by priority first, then in FIFO (first-in, first-out) order within the same priority level.PROCESSING: The request is actively being processed by our system. The AI provider is generating your response.COMPLETED: The request finished successfully. The final response is included in the same payload.FAILED: The request failed to complete. This can happen because of rate limits, provider errors, or invalid input.
QUEUED. You can track state transitions by polling the task status endpoint or receiving webhook updates.COMPLETED and FAILED tasks are stored in our system for 24 hours after completion. During this time, you can retrieve the full results using the task ID. After 24 hours, the task record and its associated response data are permanently deleted from our system.HTML URLs included in responses expire after 24 hours from generation, regardless of the task’s retention status.Step 2: receive the results
You have two options for retrieving the results of your task.Option A: webhooks (recommended)
If you provided awebhook.url in your request, we will send an HTTP POST to that URL containing the full result as soon as the task reaches a terminal state.
See Webhooks for the payload shape, retry behavior, signature verification, and troubleshooting.
Option B: polling
If you don’t provide a webhook URL, you can periodically check for the result yourself. This is called “polling.” You can make aGET request to our Get task status endpoint using the taskId you received in Step 1. Once the task is complete, the response will contain the full result.
Understanding limits
The asynchronous system handles limits in two steps.Task submission limits
When you submit a task, we only check two things:- Credit Limit: We verify you have enough credits for the task.
- Queue Limit: Your organization can have a maximum of 100,000 tasks waiting in the queue. If you exceed this, you will receive a
429 Too Many Requestserror. Please contact our team if you need this limit increased.
Task processing limits
Once your task is in the queue, our scheduler picks it up for processing. This is where your subscription’s concurrency limit is enforced. For example, if your plan allows 10 concurrent requests, our scheduler will process up to 10 of your tasks in parallel. Tasks are processed by priority first, then in the order they were received within the same priority level.Request prioritization
You can assign a priority to async tasks using thepriority field when creating a task. Priority is an integer from 1 (lowest, default) to 10 (highest).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
priority | integer | No | 1 | Task priority level (1-10). Higher numbers are processed first. |
For practical concurrency patterns and examples, see our
concurrency documentation.
Common questions
How do I cancel pending async tasks?
There is no way to cancel queued async tasks. Please be careful when posting tasks in production. Once a task is submitted and enters theQUEUED state, it will remain in the queue until it’s processed (resulting in either COMPLETED or FAILED status).
Best practices to avoid unwanted tasks:
- Test with small batches first
- Use unique
idempotencyKeyvalues to prevent duplicate submissions - Implement safeguards in your submission logic
- Monitor your queue depth via the async status endpoint
What’s the maximum queue depth?
Queue depth is limited to 100,000 tasks per organization. If you exceed this limit, you’ll receive a429 Too Many Requests error when trying to submit additional tasks.
If you need a larger queue for your use case, please contact our team.
How long do async tasks stay in the queue?
Tasks stay in the queue until they are processed, resulting in eitherCOMPLETED or FAILED status.
Check your current queue status using the async status endpoint.
How do I track the credits consumed by each task?
Both the polling response and the webhook payload include acredits object:
creditsToCharge— the estimated cost shown while the task isQUEUEDorPROCESSINGcreditsCharged— the actual amount billed once the task reachesCOMPLETEDorFAILED
creditsCharged from the terminal state to attribute cost per job. Failed tasks may still incur credits depending on how far processing got. Sync requests canceled by the client are also charged for work already done; async tasks cannot be canceled once queued.
A task came back COMPLETED but the result looks like an upstream error. What happened?
COMPLETED means cloro finished its work and returned what the upstream provider gave us. If the provider returned an error page, a captcha, or a truncated answer, that detail lives inside the response payload. Inspect the response body — FAILED is reserved for cases where cloro could not produce a result at all (network errors, internal exceptions, repeated upstream timeouts).
The async endpoint feels slow today. What should I check?
CallGET /v1/async/status to see your account’s queue depth and concurrency usage. If the queue is deep and concurrency is saturated, throughput is plan-bound — see concurrency for how to raise it.