Submitting tasks
Single task — POST /v1/tasks
Headers: Authorization: Bearer <api_key>, Content-Type: application/json
Request body
| Field | Type | Required | Description |
|---|---|---|---|
type | string | yes | image_classification, text_classification, sentiment, moderation |
data_url | string | yes | HTTPS URL to input data |
label_spec | object | yes | Must include question and options (array, ≥2 entries) |
consensus_threshold | int | no | 2–10, default 3 |
callback_url | string | no | Must match a registered webhook URL for signed delivery |
idempotency_key | string | no | Client-supplied key; repeats return the same task_id |
cURL
curl -sS -X POST https://api.asgrefinery.io/v1/tasks \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"type": "text_classification",
"data_url": "https://cdn.example.com/doc.txt",
"label_spec": {
"question": "Document category?",
"options": ["invoice", "receipt", "other"]
},
"consensus_threshold": 3,
"idempotency_key": "order-10042-line-3"
}'
Python SDK
import os
from asg_gateway import ASGGatewayClient
client = ASGGatewayClient(os.environ["API_KEY"])
resp = client.submit_task(
task_type="text_classification",
data_url="https://cdn.example.com/doc.txt",
label_spec={
"question": "Document category?",
"options": ["invoice", "receipt", "other"],
},
consensus_threshold=3,
idempotency_key="order-10042-line-3",
)
print(resp)
Success (202):
{
"task_id": "tsk_...",
"status": "pending",
"created_at": "2026-04-09T12:00:00Z"
}
Idempotent replay (200): same idempotency_key returns the existing task:
{
"task_id": "tsk_...",
"status": "pending",
"created_at": "2026-04-09T12:00:00Z",
"idempotent": true
}
Validation error (400):
{
"error": "label_spec.question is required"
}
Quota (403):
{
"error": "quota exhausted"
}
Batch — POST /v1/tasks/batch
Up to 1000 tasks per request. Optional top-level callback_url applies to each task in the batch.
curl -sS -X POST https://api.asgrefinery.io/v1/tasks/batch \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"callback_url": "https://example.com/hooks/asg",
"tasks": [
{
"type": "image_classification",
"data_url": "https://cdn.example.com/a.jpg",
"label_spec": {"question": "Animal?", "options": ["cat", "dog"]}
},
{
"type": "image_classification",
"data_url": "https://cdn.example.com/b.jpg",
"label_spec": {"question": "Animal?", "options": ["cat", "dog"]}
}
]
}'
client = ASGGatewayClient(os.environ["API_KEY"])
resp = client.submit_batch(
[
{
"type": "image_classification",
"data_url": "https://cdn.example.com/a.jpg",
"label_spec": {"question": "Animal?", "options": ["cat", "dog"]},
},
],
callback_url="https://example.com/hooks/asg",
)
print(resp)
Success (202):
{
"batch_id": "bat_...",
"task_count": 2,
"status": "accepted"
}
Task types & label_spec
| Type | label_spec | Notes |
|---|---|---|
image_classification | question + options[] | Image at data_url |
text_classification | question + options[] | Text fetched from data_url |
sentiment | question + options (e.g. positive/negative/neutral) | Same structure |
moderation | question + options (e.g. safe/unsafe + subcategories) | Same structure |
Idempotency keys
- Purpose: Exactly-once submission semantics from the client’s perspective — duplicate POSTs with the same key return the same
task_id. - Scope: Per customer (
cust_id) and key string. - TTL: Document any org-specific retention; Gateway stores the mapping in Aerospike for replay detection.
Consensus threshold
Higher thresholds increase robustness and cost; see Consensus. Default 3 matches common 2-of-3 style majority.