Skip to main content

Submitting tasks

Single task — POST /v1/tasks

Headers: Authorization: Bearer <api_key>, Content-Type: application/json

Request body

FieldTypeRequiredDescription
typestringyesimage_classification, text_classification, sentiment, moderation
data_urlstringyesHTTPS URL to input data
label_specobjectyesMust include question and options (array, ≥2 entries)
consensus_thresholdintno2–10, default 3
callback_urlstringnoMust match a registered webhook URL for signed delivery
idempotency_keystringnoClient-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

Typelabel_specNotes
image_classificationquestion + options[]Image at data_url
text_classificationquestion + options[]Text fetched from data_url
sentimentquestion + options (e.g. positive/negative/neutral)Same structure
moderationquestion + 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.