Developer docs
Quickstart
Ahel is the ground-truth layer for AI agents: hand it a company, person, email, phone, domain, or wallet and get back a verified entity with sourced receipts. One key works across REST, MCP, and the SDK. Base URL https://api.ahel.ai/v1. Every result carries its source and confidence.
1 · Get a key and make your first call
Create a key in the dashboard at /app/connect. Keys look like ahel_… and are shown once at creation — store the full value securely. Send it as a bearer token (or an X-API-Key header) on every request. New accounts start with free credits, so this works out of the box.
POST /v1/search/{type} — find an entity by email
curl https://api.ahel.ai/v1/search/email \
-H "Authorization: Bearer ahel_…" \
-H "Content-Type: application/json" \
-d '{ "query": "satoshi@example.com" }'Search returns a { meta, payload: { findings: [] } } envelope. Each finding is one source’s record, carrying its source, a confidence (0–1), a match_quality, an optional evidence url, and its data.
Response
{
"meta": { "count": 3, "duration_ms": 1840 },
"payload": {
"findings": [
{
"platform": "companies register",
"source": "ee business register",
"confidence": 0.97,
"match_quality": "exact",
"url": "https://ariregister.rik.ee/…",
"anchors": { "email": "satoshi@example.com" },
"data": { "name": "…", "reg_code": "…" }
}
]
}
}Three ways in
REST
Plain HTTPS against https://api.ahel.ai/v1 with your ahel_ key as a bearer token. The full endpoint reference is below — nothing to install.
MCP
Point any MCP-capable agent (Claude, your own runtime) at https://mcp.ahel.ai. It speaks the Model Context Protocol over a keyless OAuth handshake — the agent authorizes once and the self-describing hero tools (find, resolve, connect, verify, verify_company, lookup, invoke_provider, capabilities) appear automatically.
Claude / MCP client config
{
"mcpServers": {
"ahel": { "url": "https://mcp.ahel.ai" }
}
}SDK
A typed TypeScript client wraps the same REST surface. Construct it once with your key and call the verbs directly.
TypeScript
import { createClient } from "@ahel-technologies/arkenstone-sdk";
const ahel = createClient({ apiKey: process.env.AHEL_API_KEY }); // ahel_…
const { payload } = await ahel.search("company", "Wise", { country: "GB" });2 · Endpoint reference
Every path below is relative to https://api.ahel.ai/v1 and authenticated by your ahel_ key. POST bodies are JSON.
| Method | Path | Body | Credits |
|---|---|---|---|
| POST | /v1/search/{type}Fan out across every source for a type (email · phone · username · domain · ip · name · company · crypto …) and return the raw per-source findings. | { query } | 1 |
| POST | /v1/resolveHand one identifier and get back the single unified entity Ahel assembled across sources — merged anchors + attributes + observation history. | { type, value } | 1 |
| POST | /v1/verifyCheck one factual claim against multiple live primary sources. Returns a verdict (supported / refuted / inconclusive), an agreement score, an answer, and per-source receipts. | { claim, country? } | 10 |
| POST | /v1/verify/companySingle compound company check: registry records (EE / DK / FI / NO + Wikidata) and sanctions screening, every finding carrying its source register. | { value, country? } | 5 |
| POST | /v1/graph/expandThe Connect verb: give a seed entity, get the entities connected to it — filed officers, owners, beneficial owners, ownership graph (single-hop, stateless). | { seed: { type, value }, country?, max_connections? } | 2 |
| POST | /v1/providers/{name}/invokeHit ONE source precisely (≈10× faster than a fan-out) with managed auth + metering. Forwarding your own connected key is free; an Ahel-hosted call is 1. | provider-specific, e.g. { query, country } | 0–1 |
| GET | /v1/providersThe live source catalogue — what an agent can verify against. Metadata, not a verification call. | — | free |
| GET | /v1/creditsYour current credit balance and plan. Check it before a metered call, or use it as a budget guard in client code. | — | free |
| GET | /v1/openapiThe machine-readable OpenAPI 3 document for this surface. | — | free |
resolve, verify, verify/company and graph/expand return their own purpose-built envelope rather than the findings shape. A verify response, for example:
POST /v1/verify — response
{
"claim": "The James Webb Space Telescope launched in December 2021",
"verdict": "supported",
"agreement": 1.0,
"answer": "Yes, JWST launched on December 25, 2021.",
"sources_checked": 9,
"receipts": [
{ "provider": "live web", "stance": "supports", "confidence": 0.92,
"url": "https://…" },
{ "provider": "wikipedia", "stance": "supports", "confidence": 0.85,
"url": "https://en.wikipedia.org/wiki/James_Webb_Space_Telescope" }
]
}3 · Authentication
Every REST call needs your ahel_ key, sent either as a bearer token or an X-API-Key header. The full secret is shown once at creation and stored only as a hash — if you lose it, mint a new one. Revoking a key takes effect immediately.
Both header forms are accepted
-H "Authorization: Bearer ahel_…"
# or
-H "X-API-Key: ahel_…"401 invalid_api_key— the key is missing, malformed, revoked, or unknown (or the account is suspended).402 insufficient_credits— authenticated, but out of credits; the body carries yourbalance.429 rate_limited— too many requests for your plan; respect theRetry-Afterheader.
MCP clients skip all of this — they authorize through the OAuth handshake at https://mcp.ahel.ai instead of carrying a key.
4 · Credits and metering
Calls are metered in prepaid credits, debited up front and automatically refunded if the call fails (reserve- then-settle). A type fan-out or a cold resolve is 1 credit; a single source invoked through one of your own connected keys is free. Read-only metadata (/providers, /credits, /openapi) never costs anything.
- Search / resolve — 1 credit each.
- Provider invoke — 0 with your own connected key, 1 when Ahel hosts the source.
- Graph expand — 2 credits.
- Company check — 5 credits (registries + sanctions in one call).
- Claim verification — 10 credits (one claim across several live sources, verdict + receipts).
Check a balance any time, and top up or see the full breakdown on the pricing page.
GET /v1/credits — response
{ "payload": { "balance": 187, "plan": "free" } }5 · Errors
Errors come back as JSON with an error code (and often a detail or balance) at the matching HTTP status.
| Status | error | When |
|---|---|---|
| 400 | missing_query · unknown_search_type · missing_input | Malformed request: no query, an unknown search/resolve type, or a missing required field. |
| 401 | invalid_api_key | Missing, malformed, revoked, or unknown key (or a suspended account). Check the Authorization header. |
| 402 | insufficient_credits | Out of credits. The body carries your current balance; top up at /pricing. |
| 403 | provider_not_enabled_for_account | On /providers/{name}/invoke: that source isn't switched on under Sources for this account. |
| 404 | unknown_provider | No source with that name exists on the public catalogue. |
| 422 | needs_credential | A bring-your-own-key source was invoked without a connected credential. The body names the credentialType to add. |
| 429 | rate_limited | Per-account rate limit exceeded. The body + Retry-After header tell you how long to wait. |
| 502 | engine_error | An upstream source failed. The reserved credit is automatically refunded. |
402 — out of credits
{ "error": "insufficient_credits", "balance": 0 }429 — rate limited
{
"error": "rate_limited",
"detail": "Rate limit exceeded for the Free plan (30 requests/min). Retry in ~2s or upgrade your plan.",
"limit": 30,
"plan": "free",
"retry_after_seconds": 2
}Get a key at /app/connect · machine-readable spec at https://api.ahel.ai/v1/openapi · questions to [email protected].