Skip to content

API reference

View as Markdown

Most people never call these endpoints directly: the Python SDK and OpenTelemetry call them for you. Use this page if you are writing your own client.

  • Base URL: https://ingest.ai-tally.com
  • Authentication: every request sends your API key as Authorization: Bearer <key>. The key needs write or admin scope.
  • Where this comes from: the details below are generated from the ai-tally gateway’s own code.

POST https://ingest.ai-tally.com/v1/batches

The endpoint the Python SDK posts to. Idempotent on batch_id: resending a batch after a timeout or a 429/503 never double counts it.

Authentication: Authorization: Bearer $TALLY_KEY, a key withwrite or admin scope.

Headers

NameRequired
X-Ingest-ProtocolNo

Body (JSON): The ai-tally batch format (tally.wire.BatchRequest). Unknown fields are tolerated. With key auth the key decides the tenant, so tenant_id may be empty.

FieldTypeNotes
tenant_id (required)string
batch_idstringIdempotency key for the batch.
sdk_versionstring
client_send_ts_nsinteger
resource_spansarrayFlat span objects whose keys are gen_ai.* attributes. Prompt, completion and other body fields are never stored.
business_eventsarray
identity_linksarray
samplingobject

Success body (200)

FieldTypeNotes
batch_idstring
status"accepted" | "partial" | "rejected" | "retry"
accepted_spansinteger
partial_errorsarray
server_hintsobject
replayedboolean

Responses

StatusMeaning
200Accepted. status is accepted, or partial when some spans were rejected (see partial_errors). A batch whose batch_id was already processed returns the original result with replayed: true.
400INVALID_SCHEMA: X-Ingest-Protocol names a protocol the gateway does not support. Supported: ingest-v1.
401UNAUTHENTICATED: missing bearer token, or an invalid or revoked key.
403FORBIDDEN_SCOPE: the key has read scope and cannot write spans. TENANT_MISMATCH: the body names a tenant the key is not bound to.
422Every span in the batch was rejected (a BatchResponse with status: rejected and per-span partial_errors), or the body is malformed ({"detail": "..."}).
429RATE_LIMITED, QUOTA_EXCEEDED: back off for Retry-After seconds and resend the same body with the same batch_id. Header: Retry-After.
503Temporarily unable to accept the batch (status: retry). Includes IDEMPOTENCY_UNAVAILABLE. Resend the same body with the same batch_id; it is never double counted. Header: Retry-After.

Each span is a flat object of gen_ai.* attributes. Give each batch its own batch_id: sending the same batch_id again returns the first result instead of counting the batch twice, which makes retries safe.

Terminal window
curl https://ingest.ai-tally.com/v1/batches \
-H "Authorization: Bearer $TALLY_KEY" \
-H "Content-Type: application/json" \
-d '{"tenant_id": "", "batch_id": "my-batch-0001", "resource_spans": [{
"trace_id": "t1", "span_id": "s1",
"gen_ai.system": "openai", "gen_ai.operation.name": "chat",
"gen_ai.request.model": "gpt-4o-mini",
"gen_ai.usage.input_tokens": 12, "gen_ai.usage.output_tokens": 5}]}'

POST https://ingest.ai-tally.com/v1/otlp/traces

Accepts an OTLP ExportTraceServiceRequest encoded as JSON (OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/json). Protobuf is not supported. Spans are grouped by gen_ai.operation.name.

Authentication: Authorization: Bearer $TALLY_KEY, a key withwrite or admin scope.

Body (JSON): OTLP ExportTraceServiceRequest (JSON encoding).

FieldTypeNotes
resourceSpansarray

Success body (200)

FieldTypeNotes
batch_idstring
status"accepted" | "partial" | "rejected" | "retry"
accepted_spansinteger
partial_errorsarray
server_hintsobject
replayedboolean

Responses

StatusMeaning
200Accepted. status is accepted, or partial when some spans were rejected (see partial_errors). A batch whose batch_id was already processed returns the original result with replayed: true.
401UNAUTHENTICATED: missing bearer token, or an invalid or revoked key.
403FORBIDDEN_SCOPE: the key has read scope and cannot write spans. TENANT_MISMATCH: the body names a tenant the key is not bound to.
422Every span in the batch was rejected (a BatchResponse with status: rejected and per-span partial_errors), or the body is malformed ({"detail": "..."}).
429RATE_LIMITED, QUOTA_EXCEEDED: back off for Retry-After seconds and resend the same body with the same batch_id. Header: Retry-After.
503Temporarily unable to accept the batch (status: retry). Includes IDEMPOTENCY_UNAVAILABLE. Resend the same body with the same batch_id; it is never double counted. Header: Retry-After.
Terminal window
curl https://ingest.ai-tally.com/v1/otlp/traces \
-H "Authorization: Bearer $TALLY_KEY" \
-H "Content-Type: application/json" \
-d '{"resourceSpans": [{"scopeSpans": [{"spans": [{
"traceId": "5b8efff798038103d269b633813fc60c", "spanId": "eee19b7ec3c1b174",
"name": "chat", "startTimeUnixNano": "'"$(date +%s)000000000"'",
"attributes": [
{"key": "gen_ai.system", "value": {"stringValue": "openai"}},
{"key": "gen_ai.operation.name", "value": {"stringValue": "chat"}},
{"key": "gen_ai.request.model", "value": {"stringValue": "gpt-4o-mini"}},
{"key": "gen_ai.usage.input_tokens", "value": {"intValue": "12"}},
{"key": "gen_ai.usage.output_tokens", "value": {"intValue": "5"}}]}]}]}]}'

GET https://ingest.ai-tally.com/v1/tenant/hmac-key

Returns the active HMAC-SHA256 key the SDK uses to hash account ids before they leave your process. Always requires a key with write or admin scope. The response is a secret: do not log it.

Authentication: Authorization: Bearer $TALLY_KEY, a key withwrite or admin scope.

Success body (200)

FieldTypeNotes
tenant_idstring
key_versionstringKey version, like v1.
key_material_b64stringTreat as a secret.
algorithm"HMAC-SHA256"

Responses

StatusMeaning
200The active key and its version.
401UNAUTHENTICATED: missing bearer token, or an invalid or revoked key.
403FORBIDDEN_SCOPE: a read key cannot fetch key material. HMAC_EXPORT_DISABLED: key export is disabled for this organization.
404No key material exists for this organization. Hash nothing and send spans unattributed rather than sending raw ids.
503The key store could not be reached. Retryable; no key material was returned.

The reply contains your organization’s secret hashing key. Keep it out of logs. Most apps never call this: tally.hash_account calls it for you.

Terminal window
curl https://ingest.ai-tally.com/v1/tenant/hmac-key \
-H "Authorization: Bearer $TALLY_KEY"
  • Sending from Python? The Python SDK handles batching, retries and hashing for you.