Skip to content

Companions API

The Companions API orchestrates multi-persona LLM modes — a single answer, several answers in parallel, an expert panel, or a moderated discussion — behind one simple REST interface. You send a prompt and a mode; the platform runs the personas, bills the exact provider cost, and returns a typed result.

Base URL      https://api.humx.ai
Version       v1   (every path is prefixed /v1)
Content type  application/json

How it works

Every run is asynchronous. A run-producing request (like POST /v1/completion) returns immediately with a job envelope — an id of the form job-<uuid> and a pending status. You then read the result from the unified /v1/jobs/{id} surface, either by polling or by subscribing to a live event stream.

POST /v1/completion   ──►   { "id": "job-abc…", "status": "pending" }
GET  /v1/jobs/job-abc…  ◄────────────┘   poll until status is terminal
                             or
GET  /v1/jobs/job-abc…/stream            subscribe (Server-Sent Events)

This one envelope (JobStatus) is returned by every run-producing endpoint, so a client learns the shape once and reuses it everywhere.

Quickstart

# 1. Enqueue a single-persona answer.
curl https://api.humx.ai/v1/completion \
  -H "Authorization: ApiKey $COMPANIONS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "prompt": "Explain rate limiting to a new engineer.", "mode": "answer" }'
# → { "id": "job-1a2b...", "status": "pending" }

# 2. Poll the job until it is complete.
curl https://api.humx.ai/v1/jobs/job-1a2b... \
  -H "Authorization: ApiKey $COMPANIONS_API_KEY"
# → { "status": "complete", "content": { "shape": "answer", "response": "..." } }
import os, time, requests

headers = {"Authorization": f"ApiKey {os.environ['COMPANIONS_API_KEY']}"}

# 1. Enqueue a run.
job = requests.post(
    "https://api.humx.ai/v1/completion",
    headers=headers,
    json={"prompt": "Explain rate limiting to a new engineer.", "mode": "answer"},
).json()

# 2. Poll until it finishes.
while job["status"] not in ("complete", "failed"):
    time.sleep(1.0)
    job = requests.get(f"https://api.humx.ai/v1/jobs/{job['id']}", headers=headers).json()

print(job["content"]["response"])
const headers = {
  Authorization: `ApiKey ${process.env.COMPANIONS_API_KEY}`,
  "Content-Type": "application/json",
};

// 1. Enqueue a run.
let job = await (await fetch("https://api.humx.ai/v1/completion", {
  method: "POST",
  headers,
  body: JSON.stringify({ prompt: "Explain rate limiting to a new engineer.", mode: "answer" }),
})).json();

// 2. Poll until it finishes.
while (!["complete", "failed"].includes(job.status)) {
  await new Promise((r) => setTimeout(r, 1000));
  job = await (await fetch(`https://api.humx.ai/v1/jobs/${job.id}`, { headers })).json();
}

console.log(job.content.response);
const headers = {
  Authorization: `ApiKey ${process.env.COMPANIONS_API_KEY!}`,
  "Content-Type": "application/json",
};

// 1. Enqueue a run.
let job = await (await fetch("https://api.humx.ai/v1/completion", {
  method: "POST",
  headers,
  body: JSON.stringify({ prompt: "Explain rate limiting to a new engineer.", mode: "answer" }),
})).json();

// 2. Poll until it finishes.
while (!["complete", "failed"].includes(job.status)) {
  await new Promise((r) => setTimeout(r, 1000));
  job = await (await fetch(`https://api.humx.ai/v1/jobs/${job.id}`, { headers })).json();
}

console.log(job.content.response);

See Authentication to mint a key, then Completion for the full request shape.

Reference

Resource What it does
Completion Enqueue an engine run — one answer, parallel answers, a panel, or a discussion.
Jobs Poll or stream any run, and return client-side tool outputs.
Models List the model slugs you may select, with their parameter ranges.
Discover One read of every team and companion you can use.
Billing Read your balance and the transaction ledger.
Account Manage your profile, usage history, API keys, and integrations.

Errors

The API uses conventional HTTP status codes.

Status Meaning
200 Success.
204 Success, no body (e.g. a delete).
401 Missing or invalid credentials.
402 Insufficient balance to run.
403 Authenticated, but not allowed.
404 No such resource (or not yours).
409 Conflict (e.g. a resource limit reached).
422 The request body failed validation — the response lists each offending field.

A 422 body follows FastAPI's detail convention: a list of entries, each naming the field (loc), a machine-readable type, and a human msg.

{
  "detail": [
    {
      "type": "prompt_or_messages",
      "loc": ["body"],
      "msg": "provide exactly one of prompt or messages"
    }
  ]
}