Skip to main content

Quickstart: your first label in 5 minutes

This tutorial walks from registration to a settled consensus label using the ASG Gateway API. Examples use the hosted API at https://api.asgrefinery.io; swap in http://localhost:8081 when running the Gateway locally against a dev stack.

Prerequisites

  • Hosted path: HTTPS client (curl) and an ASG account (register below).
  • Local path: Docker, ASG Refinery stack with Aerospike reachable from the Gateway, and Gateway listening on port 8081 (see Refinery / Gateway READMEs).
tip

Keep your API key in an environment variable (export ASG_API_KEY=...) — never commit keys to source control.

Step 1: Register a customer

Create a customer and receive a sandbox API key (shown once).

curl -sS -X POST https://api.asgrefinery.io/v1/customers \
-H 'Content-Type: application/json' \
-d '{"name":"Demo","email":"demo@example.com"}'

Example response (201):

{
"customer_id": "cust_...",
"api_key": "sk_sandbox_...",
"tier": "sandbox",
"label_quota": 500,
"message": "Store this API key securely — it cannot be retrieved again."
}

Save api_key and export it:

export API_KEY='sk_sandbox_...'

What happened: The Gateway created a tenant record, issued a sandbox key with a label quota (500 free labels by default), and returned the raw key exactly once.

Error example (409):

{
"error": "email already registered"
}

Step 2: Submit a task

cURL

curl -sS -X POST https://api.asgrefinery.io/v1/tasks \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"type": "image_classification",
"data_url": "https://example.com/image.jpg",
"label_spec": {
"question": "Animal?",
"options": ["cat", "dog"]
},
"consensus_threshold": 3
}'

Python SDK

import os
from asg_gateway import ASGGatewayClient

client = ASGGatewayClient(api_key=os.environ["API_KEY"])
resp = client.submit_task(
task_type="image_classification",
data_url="https://example.com/image.jpg",
label_spec={"question": "Animal?", "options": ["cat", "dog"]},
consensus_threshold=3,
)
print(resp)

Example response (202):

{
"task_id": "tsk_...",
"status": "pending",
"created_at": "2026-04-09T12:00:00Z"
}

Copy task_id for the next steps.

What happened: The Gateway stored the task in Aerospike with status=pending. ASG Refinery’s Task Router picks it up, workers submit labels, then consensus and settlement run in the pipeline.

Step 3: Wait for consensus

While Refinery runs:

  1. Workers claim the task → in_progress.
  2. Enough labels arrive for your consensus threshold → consensus computes a consensus label.
  3. Settlement pays agreeing workers on BSV → settled, bsv_txid recorded.

You do not need to poll rapidly at first; see Retrieving results for backoff guidance.

Step 4: Get your result

Replace tsk_XXX with your task_id.

curl -sS -w "\nHTTP %{http_code}\n" \
-H "Authorization: Bearer $API_KEY" \
https://api.asgrefinery.io/v1/tasks/tsk_XXX/result

While labeling (202):

{
"status": "in_progress",
"message": "Task is still being labeled."
}

When verified / settled (200):

{
"task_id": "tsk_...",
"status": "settled",
"consensus_label": "cat",
"confidence": 0.6666666666666666,
"worker_count": 3,
"agreement_count": 2,
"label_spec": {
"question": "Animal?",
"options": ["cat", "dog"]
},
"settlement": {
"bsv_txid": "abc123...",
"total_cost_sats": 1000,
"settled_at": "2026-04-09T12:05:00Z"
}
}

What happened: GET /v1/tasks/{id}/result returns 202 until the task reaches verified or settled, then 200 with consensus_label, confidence, worker counts, and settlement.bsv_txid.

Python SDK (poll)

result = client.poll_result("tsk_XXX", timeout=300, interval=5)
print(result["consensus_label"], result["settlement"]["bsv_txid"])

Step 5: Verify on-chain

Open the transaction on a BSV explorer (WhatsOnChain):

https://whatsonchain.com/tx/{bsv_txid}

Replace {bsv_txid} with the value from settlement.bsv_txid. You now have an immutable receipt tying the label to a chain transaction.

info

Integration guide note: Refinery’s live consensus engine may still use a fixed 3-label / 2-of-3 path while consensus_threshold is stored for future engine behavior — see How it works.


Next steps: Submit tasks in bulk | Set up webhooks | Explore the dashboard