Docs
Quickstart and reference for the public classify endpoint. One stable URL, one organization API key, and a response contract that does not change under you.
Quickstart
Three steps from account to a verified classification.
Step 1
Create an API key
Sign up, open your organization settings, and create an API key. The secret is shown once — store it somewhere safe.
Step 2
Send the request
POST to the classify endpoint with a managed model ID from the model catalog. The example below classifies one string.
Step 3
See it in the dashboard
The request appears in your organization’s logs and usage with its outcome, latency, and exact cost. Logs arrive with a short delay.
Classify text
curl -X POST https://api.truepositive.ai/v1/classify \
-H "Authorization: Bearer $TRUEPOSITIVE_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "model": "truepositive/moderation", "input": "hello" }'Replace $TRUEPOSITIVE_API_KEY with your organization API key. This page never embeds a live secret.
Authentication
Every request carries an organization API key as a Bearer token in the Authorization header. Keys start with tp_live_, are created and revoked in organization settings, and one key authenticates every managed model. Usage is attributed to the organization that owns the key — never to an individual project.
Request
POST https://api.truepositive.ai/v1/classify with a JSON body.
| Field | Type | Limits |
|---|---|---|
| model | string | A managed model ID such as truepositive/moderation. See Models. |
| input | string or string[] | One string, or a batch of 1–32 strings. Each string holds 1–16,384 characters. |
Batches return one result per input string, in order, identified by its index. A batch counts each string as one billed item.
Idempotent retries
Safe retries are built in. Send an Idempotency-Key header with any request you might retry.
- Keys are up to 128 characters: letters, digits, and
.,_,:,-. - Repeating a key with the same request body replays the recorded response — the retry is not charged again.
- Reusing a key with a different body is rejected with
idempotency_conflict. - If the original request is still processing, the retry is rejected with
idempotency_in_progress; try again shortly.
Classify with an idempotency key
curl -X POST https://api.truepositive.ai/v1/classify \
-H "Authorization: Bearer $TRUEPOSITIVE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-4187-first-check" \
-d '{ "model": "truepositive/moderation", "input": "hello" }'Response
The public response is stable. It carries classification results and billing facts — internal model lineage and serving details are never exposed.
Success — 200
{
"id": "req_9f4c2ab1",
"model": "truepositive/moderation",
"results": [
{ "index": 0, "scores": { "Safe": 0.98, "Harassment": 0.01 } }
],
"latency_ms": 141,
"usage": {
"input_items": 1,
"cost": { "amount": "0.001000", "currency": "USD" }
}
}results[].scoresmaps each label to a score between 0 and 1. An empty map means no label applied.usage.cost.amountis the exact USD debit for the request, to six decimal places;usage.input_itemscounts the billed strings.ididentifies the request across logs, usage, and support.
The example above is illustrative; scores, latency, and cost come from your actual requests.
Error — non-2xx
{
"id": "req_9f4c28d2",
"error": { "code": "insufficient_credits" }
}| Status | Code | Meaning |
|---|---|---|
| 400 | bad_request | Malformed JSON, or model/input fields outside the documented limits. |
| 401 | unauthorized | Missing, malformed, or revoked organization API key. |
| 402 | insufficient_credits | The organization is out of credits. Add credits, then retry. |
| 403 | entitlement_required | The organization's plan does not cover this usage. |
| 404 | not_found | Unknown path or model ID. Check the model ID on the Models page. |
| 405 | method_not_allowed | The endpoint only accepts POST. |
| 409 | idempotency_conflict | The Idempotency-Key was already used with a different request body. |
| 409 | idempotency_in_progress | A request with the same Idempotency-Key is still processing; retry shortly. |
| 413 | payload_too_large | The request body exceeds the accepted size. |
| Status | Code | Meaning |
|---|---|---|
| 500 | internal_error | Unexpected server failure. Safe to retry with the same Idempotency-Key. |
| 502 | bad_gateway | The model returned an unusable response. Safe to retry with the same Idempotency-Key. |
| 503 | unavailable | The model is temporarily unavailable. Safe to retry with the same Idempotency-Key. |
| 503 | gateway_disabled | The API is temporarily disabled. Safe to retry with the same Idempotency-Key. |
| 504 | gateway_timeout | The model did not respond in time. Safe to retry with the same Idempotency-Key. |
Payload retention
Your organization decides whether payloads are stored. The choice is captured per request, at the moment the request is received.
- When payload storage is on, request and response payloads are kept for the configured period — 1 to 365 days — then deleted.
- When payload storage is off, payloads are never stored. Request metadata and usage are always logged either way.
- Changing the setting affects future requests; earlier requests keep the setting that was active when they were received.
- Owners and admins manage retention in organization settings.
Where to go next
Model catalog
Managed model IDs, capabilities, and the same canonical request.
Logs and usage
Verify requests, outcomes, latency, and credit burn in your organization.
Open the dashboard, select your organization, and choose Logs or Usage.