Free Tier API

Zero-auth endpoints for supporting identity and inbox experiments. Create one disposable email identity, use it only in customer- controlled or explicitly authorized flows, then poll for redacted extraction evidence — no API key required.

Rate limits

Free tier endpoints are rate-limited to 10 requests per minute per IP. Each IP address may hold at most 1 active identity at a time, with a 24-hour TTL. For higher limits and multiple concurrent identities, upgrade to a paid plan.

Create a disposable identity

POST/v1/free/identity

Provision a single disposable email identity keyed to the caller's IP address. No authentication headers are required. The identity expires automatically after 24 hours.

Request body

FieldTypeRequiredDescription
labelstringNoOptional human-readable label for the identity

curl

curl -X POST https://api.aidenid.com/v1/free/identity \
  -H "Content-Type: application/json" \
  -d '{ "label": "github-signup" }'

Python

import requests

resp = requests.post(
    "https://api.aidenid.com/v1/free/identity",
    json={"label": "github-signup"},
)
data = resp.json()
print(data["id"], data["status"])

TypeScript

const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 10_000);
const res = await fetch("https://api.aidenid.com/v1/free/identity", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ label: "github-signup" }),
  signal: controller.signal,
});
clearTimeout(timeout);
const { id, email, token } = await res.json();

Response 201 Created

{
  "id": "free_a1b2c3d4e5",
  "email": "a1b2c3d4e5@inbox.aidenid.com",
  "label": "github-signup",
  "token": "ftok_x9y8z7w6v5",
  "status": "provisioned",
  "expires_at": "2026-04-07T10:00:00Z"
}
Ephemeral token

The token returned at creation is the only credential for this identity. Store it — it cannot be retrieved again. All subsequent requests for this identity require it as a query parameter.

Check identity status

GET/v1/free/identity/{id}

Retrieve the current status of a free-tier identity. Requires the ephemeral token from creation.

Query parameters

ParameterTypeRequiredDescription
tokenstringYesEphemeral token returned at identity creation

curl

curl "https://api.aidenid.com/v1/free/identity/free_a1b2c3d4e5?token=ftok_x9y8z7w6v5"

Response 200 OK

{
  "id": "free_a1b2c3d4e5",
  "email": "a1b2c3d4e5@inbox.aidenid.com",
  "label": "github-signup",
  "status": "active",
  "expires_at": "2026-04-07T10:00:00Z"
}

Poll for extracted code

GET/v1/free/identity/{id}/extraction

Poll for an extracted OTP, verification code, or magic link. Returns 202 Accepted while the extraction is still pending and 200 OK when a value has been extracted.

Query parameters

ParameterTypeRequiredDescription
tokenstringYesEphemeral token returned at identity creation

curl

curl "https://api.aidenid.com/v1/free/identity/free_a1b2c3d4e5/extraction?token=ftok_x9y8z7w6v5"

Response — pending 202 Accepted

{
  "status": "pending",
  "retryAfterSeconds": 3
}

Response — ready 200 OK

{
  "status": "ready",
  "type": "otp",
  "has_secret": true,
  "redacted_value": "***",
  "extracted_at": "2026-04-06T10:05:02Z",
  "confidence": 0.99
}

Complete agent flow example

This end-to-end example demonstrates the full lifecycle: create an identity, use the email address in an authorized flow, then poll until redacted extraction evidence arrives.

Python

import requests, time

BASE = "https://api.aidenid.com/v1/free"

# Step 1: Create a disposable identity
identity = requests.post(f"{BASE}/identity", json={"label": "demo-signup"}).json()
email = identity["email"]
token = identity["token"]
identity_id = identity["id"]

print(f"Identity provisioned: {identity_id}")

# Step 2: Use the email in an authorized customer-controlled flow
# ... your signup automation here ...

# Step 3: Poll for redacted extraction evidence
for attempt in range(20):
    resp = requests.get(f"{BASE}/identity/{identity_id}/extraction", params={"token": token})

    if resp.status_code == 200:
        data = resp.json()
        print(f"Extraction ready: {data['type']}")
        break

    retry_after = resp.json().get("retryAfterSeconds", 3)
    print(f"Pending... retrying in {retry_after}s")
    time.sleep(retry_after)
else:
    print("Timed out waiting for extraction")

TypeScript

const BASE = "https://api.aidenid.com/v1/free";
const fetchWithTimeout = async (url: string, init: RequestInit = {}, timeoutMs = 10_000) => {
  const controller = new AbortController();
  const timeout = setTimeout(() => controller.abort(), timeoutMs);
  try {
    return await fetch(url, { ...init, signal: controller.signal });
  } finally {
    clearTimeout(timeout);
  }
};

// Step 1: Create a disposable identity
const identity = await fetchWithTimeout(`${BASE}/identity`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ label: "demo-signup" }),
}).then((r) => r.json());

const { id, email, token } = identity;
console.log("Identity provisioned:", id);

// Step 2: Use the email in an authorized customer-controlled flow
// ... your signup automation here ...

// Step 3: Poll for redacted extraction evidence
for (let i = 0; i < 20; i++) {
  const res = await fetchWithTimeout(
    `${BASE}/identity/${id}/extraction?token=${token}`
  );
  const data = await res.json();

  if (res.status === 200) {
    console.log("Extraction ready:", data.type);
    break;
  }

  const wait = data.retryAfterSeconds ?? 3;
  console.log(`Pending... retrying in ${wait}s`);
  await new Promise((r) => setTimeout(r, wait * 1000));
}

Error codes

CodeStatusDescription
ip_limit_reached429This IP already has an active free-tier identity
rate_limited429Too many requests — retry after the indicated interval
identity_not_found404Identity does not exist or has expired
invalid_token401The ephemeral token is missing or incorrect
identity_expired410The identity has passed its 24-hour TTL
Moving to production?

The free tier is designed for experimentation and single-use agent flows. For production workloads with concurrent identities, custom domains, webhooks, and higher rate limits, see the pricing page or Billing API to upgrade programmatically.

Related