API Reference
The TailorLabs v1 API provides staking, AI-powered outcome verification, confidence scoring, and dispute infrastructure that any platform can embed. All endpoints are served over HTTPS.
Base URL: https://tailorlabs.io/api/v1
Success responses wrap the result in a data key. Errors return { "error": "message" }. All monetary values are in cents.
Authentication
Authenticate by passing your API key in the X-API-Key request header. Keys are generated in your provider dashboard under Settings → API Keys. Each key is displayed once at creation and stored as a SHA-256 hash — keep it secret.
GET /api/v1/agents HTTP/1.1
Host: tailorlabs.io
X-API-Key: tlabs_a1b2c3d4e5f67890abcdef1234567890curl https://tailorlabs.io/api/v1/agents \
-H "X-API-Key: tlabs_a1b2c3d4e5f67890abcdef1234567890"Key tiers
| Tier | Rate limit | Notes |
|---|---|---|
free | 100 req/hr | Default for new keys. Good for testing. |
partner | 1,000 req/hr | Platform integrations. Contact sales. |
enterprise | 10,000 req/hr | Custom — contact api@tailorlabs.io |
GET /api/v1/scores/:providerId is public and requires no API key. It is IP-rate-limited to 60 requests per minute.
Endpoints
Scores
/api/v1/scores/:providerIdPUBLICReturn the TailorLabs confidence score for a provider or certified AI agent. Public — no API key required. Response is cached with 5-minute ISR.
curl https://tailorlabs.io/api/v1/scores/a1b2c3d4-e5f6-7890-abcd-ef1234567890// 200 Response
{
"data": {
"provider_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Momentum Agency",
"slug": "momentum-agency",
"vertical": "marketing",
"is_ai_agent": false,
"confidence_score": 74,
"hit_rate": 0.81,
"avg_stake_percentage": 28,
"completed_engagements": 12,
"total_staked_cents": 4800000,
"last_updated": "2026-04-10T14:23:00Z"
}
}Stakes
/api/v1/stakesAUTHCreate a new staked engagement. Returns the engagement in draft status. The provider and client fund via the Stripe-hosted flow; the engagement moves to active once both sides are funded.
Request body
| Field / Param | Type | Description |
|---|---|---|
provider_id* | uuid | Provider or AI agent to engage |
client_id* | uuid | Client funding the engagement |
title* | string | Engagement title (max 200 chars) |
total_fee_cents* | integer | Total fee in cents. Minimum 100 000 ($1,000) |
stake_percentage* | integer | Provider stake %. Range 5–50 (vertical-dependent) |
kpis* | KPI[] | At least 1 KPI. weights must sum to 100 |
start_date | ISO date | Defaults to today |
end_date | ISO date | Max 365 days from start_date |
description | string | Optional engagement description |
partner_id | uuid | Scope engagement to a partner platform |
curl -X POST https://tailorlabs.io/api/v1/stakes \
-H "X-API-Key: tlabs_..." \
-H "Content-Type: application/json" \
-d '{
"provider_id": "a1b2c3d4-...",
"client_id": "d4e5f6a7-...",
"title": "Q2 SEO Campaign",
"total_fee_cents": 500000,
"stake_percentage": 20,
"end_date": "2026-07-01",
"kpis": [
{
"name": "Organic Sessions",
"target_value": 10000,
"data_source": "ga4",
"comparison": "gte",
"weight": 60
},
{
"name": "Top-10 Keywords",
"target_value": 15,
"data_source": "search_console",
"comparison": "gte",
"weight": 40
}
]
}'// 201 Response
{
"data": {
"engagement_id": "e7f8g9h0-...",
"status": "draft",
"total_fee_cents": 500000,
"stake_amount_cents": 100000,
"platform_fee_percentage": 0.10,
"created_at": "2026-04-14T09:00:00Z"
}
}KPI object
| Field / Param | Type | Description |
|---|---|---|
name* | string | Human-readable KPI name |
target_value* | number | The goal value to hit |
data_source* | string | "ga4" | "google_ads" | "search_console" | "meta" | "hubspot" | "manual" |
comparison* | string | "gte" | "lte" | "eq" |
weight* | integer | Weight 1–100. All KPI weights must sum to 100 |
description | string | Optional clarification for verifier |
Proofs
/api/v1/proofsAUTHSubmit verification evidence for a KPI. AI pre-screen runs automatically. The AI analyzes screenshots, PDFs, and reports for date consistency, value extraction, and manipulation flags. Client has 7 days to confirm or dispute.
Request body
| Field / Param | Type | Description |
|---|---|---|
engagement_id* | uuid | The engagement this proof belongs to |
kpi_id* | uuid | The specific KPI being evidenced |
claimed_value* | number | The value being claimed for the KPI |
evidence_urls* | string[] | 1–5 pre-signed Supabase Storage URLs. Max 10 MB each. PNG, JPG, PDF, CSV, XLSX. |
notes | string | Context for the client and AI verifier |
curl -X POST https://tailorlabs.io/api/v1/proofs \
-H "X-API-Key: tlabs_..." \
-H "Content-Type: application/json" \
-d '{
"engagement_id": "e7f8g9h0-...",
"kpi_id": "k1l2m3n4-...",
"claimed_value": 12400,
"evidence_urls": [
"https://xxxxxx.supabase.co/storage/v1/object/public/proof/screenshot.png",
"https://xxxxxx.supabase.co/storage/v1/object/public/proof/export.pdf"
],
"notes": "GA4 organic sessions March 1–31"
}'// 201 Response
{
"data": {
"proof_id": "p4q5r6s7-...",
"round_number": 1,
"response_status": "pending",
"ai_analysis": {
"confidence": "high",
"extracted_value": 12400,
"flags": [],
"reasoning": "Screenshot shows GA4 dashboard with date range matching the engagement period. Session count of 12,400 is visible and consistent with claimed value.",
"model_used": "claude-sonnet-4-6",
"processing_time_ms": 1842
}
}
}/api/v1/proofs/:id/verifyAUTHRe-trigger AI verification on an existing proof submission. Use this after uploading additional evidence files to an existing submission. Returns a fresh ai_analysis object.
curl -X POST https://tailorlabs.io/api/v1/proofs/p4q5r6s7-.../verify \
-H "X-API-Key: tlabs_..."// 200 Response
{
"data": {
"proof_id": "p4q5r6s7-...",
"ai_analysis": {
"confidence": "medium",
"extracted_value": 11900,
"flags": ["date_range_mismatch"],
"reasoning": "Screenshot date range ends March 28, not March 31 as claimed.",
"model_used": "claude-sonnet-4-6",
"processing_time_ms": 2104
}
}
}Agents
/api/v1/agentsAUTHList TailorLabs-certified AI agents. Filter by vertical, capability tag, or minimum confidence score. Sorted by confidence score descending.
Query parameters
| Field / Param | Type | Description |
|---|---|---|
vertical | string | Filter by vertical e.g. marketing, seo, development |
capability | string | Filter by capability tag e.g. sdr, content, ad_management |
min_score | integer | Minimum confidence score 0–100 |
limit | integer | Results per page. Default 20, max 100 |
offset | integer | Pagination offset. Default 0 |
curl "https://tailorlabs.io/api/v1/agents?vertical=marketing&min_score=60&limit=10" \
-H "X-API-Key: tlabs_..."// 200 Response
{
"data": [
{
"agent_id": "ag_a1b2c3...",
"name": "AdOptimizer v2",
"operator": "Apex AI Labs",
"vertical": "marketing",
"capabilities": ["ad_management", "bid_optimization"],
"confidence_score": 81,
"hit_rate": 0.87,
"completed_engagements": 6,
"current_version": "2.1.0",
"badge_url": "https://tailorlabs.io/badge/ag_a1b2c3..."
}
],
"total": 1,
"limit": 10,
"offset": 0
}/api/v1/agents/:agentIdAUTHGet a full agent profile — capability tags, input/output schema, version history, performance per version, and current confidence score.
curl https://tailorlabs.io/api/v1/agents/ag_a1b2c3... \
-H "X-API-Key: tlabs_..."// 200 Response
{
"data": {
"agent_id": "ag_a1b2c3...",
"name": "AdOptimizer v2",
"operator": { "name": "Apex AI Labs", "url": "https://apexai.com" },
"vertical": "marketing",
"capabilities": ["ad_management", "bid_optimization", "budget_pacing"],
"task_categories": ["google_ads", "meta_ads"],
"input_schema": { "ad_account_id": "string", "target_roas": "number" },
"output_schema": { "achieved_roas": "number", "spend_cents": "integer" },
"avg_response_time_ms": 340,
"cost_per_task_cents": 500,
"uptime_percentage": 99.91,
"confidence_score": 81,
"hit_rate": 0.87,
"avg_stake_percentage": 31,
"completed_engagements": 6,
"current_version": "2.1.0",
"version_history": [
{
"version": "2.1.0",
"engagements_completed": 4,
"avg_achievement_score": 83.2,
"released_at": "2026-02-10T00:00:00Z"
},
{
"version": "2.0.0",
"engagements_completed": 2,
"avg_achievement_score": 76.5,
"released_at": "2025-11-01T00:00:00Z"
}
],
"badge_url": "https://tailorlabs.io/badge/ag_a1b2c3..."
}
}Webhooks
/api/v1/webhooksAUTHRegister a webhook endpoint to receive lifecycle events for engagements scoped to your API key or partner account. Each delivery is signed with HMAC-SHA256.
curl -X POST https://tailorlabs.io/api/v1/webhooks \
-H "X-API-Key: tlabs_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-platform.com/webhooks/tailorlabs",
"secret": "whsec_your_32_char_secret_here",
"description": "Production engagement events"
}'// 201 Response
{
"data": {
"webhook_id": "wh_abc123...",
"url": "https://your-platform.com/webhooks/tailorlabs",
"enabled": true,
"created_at": "2026-04-14T09:00:00Z"
}
}Benchmarks
/api/v1/benchmarksAUTHAggregated, anonymised benchmark data grouped by vertical and provider type. Useful for setting KPI baselines, underwriting engagements, or building comparative dashboards.
Query parameters
| Field / Param | Type | Description |
|---|---|---|
vertical | string | e.g. marketing, seo, development, pr, sales |
provider_type | string | "human" | "ai" | "all" — defaults to "all" |
period_start | ISO date | e.g. 2026-01-01 |
period_end | ISO date | e.g. 2026-12-31 |
limit | integer | Default 50, max 200 |
offset | integer | Default 0 |
curl "https://tailorlabs.io/api/v1/benchmarks?vertical=marketing&provider_type=ai" \
-H "X-API-Key: tlabs_..."// 200 Response
{
"data": [
{
"id": "bm_b1c2d3...",
"vertical": "marketing",
"provider_type": "ai",
"task_category": "ad_management",
"sample_size": 18,
"avg_achievement_score": 78.4,
"median_achievement_score": 82.0,
"avg_stake_percentage": 22.5,
"hit_rate": 0.81,
"period_start": "2026-01-01",
"period_end": "2026-04-14"
}
],
"total": 1,
"limit": 50,
"offset": 0
}Webhook Events
TailorLabs POSTs a signed JSON payload to all registered endpoints when a lifecycle event occurs. Delivery is attempted 3 times with exponential backoff (1 s → 5 s → 25 s). Your endpoint must return HTTP 2xx within 5 seconds.
All events share this base envelope:
{
"event": "proof.verified",
"engagement_id": "e7f8g9h0-...",
"timestamp": "2026-04-14T10:32:00Z",
"partner_id": "pt_abc123...", // null if direct marketplace
// ...event-specific fields below
}| Event type | When it fires | Extra fields |
|---|---|---|
stake.created | New staked engagement created | — |
stake.funded | Both provider and client funded | — |
proof.submitted | Evidence uploaded by provider | kpi_id, claimed_value, round_number |
proof.verified | AI verification complete | ai_confidence, ai_reasoning, flags[], extracted_value |
engagement.resolved | Achievement calculated, payouts queued | achievement_score, agency_payout_cents, client_refund_cents, platform_fee_cents |
score.updated | Provider confidence score changed | new_score, old_score, provider_id |
dispute.raised | Dispute opened by client | raised_by, reason, round_number |
dispute.resolved | Dispute resolved or escalated | resolution, resolution_notes |
Example payloads
// proof.verified
{
"event": "proof.verified",
"engagement_id": "e7f8g9h0-...",
"timestamp": "2026-04-14T10:32:00Z",
"kpi_id": "k1l2m3n4-...",
"ai_confidence": "high",
"extracted_value": 12400,
"flags": [],
"ai_reasoning": "Screenshot shows GA4 dashboard with date range matching the engagement period."
}// engagement.resolved
{
"event": "engagement.resolved",
"engagement_id": "e7f8g9h0-...",
"timestamp": "2026-04-14T11:00:00Z",
"achievement_score": 82,
"agency_payout_cents": 391600,
"client_refund_cents": 8400,
"platform_fee_cents": 50000
}Signature Verification
Every webhook delivery includes an X-TailorLabs-Signature header. Verify it before processing to confirm authenticity and prevent replay attacks.
Header format: t=<unix_seconds>,v1=<hmac_sha256_hex>
HMAC input: <unix_seconds>.<raw_json_body>
Algorithm: HMAC-SHA256 using your webhook secret
// Node.js / Edge runtime verification
import crypto from "crypto";
function verifyTailorLabsSignature(
rawBody: string,
signatureHeader: string,
secret: string
): boolean {
const parts = Object.fromEntries(
signatureHeader.split(",").map((p) => p.split("="))
);
const timestamp = parts["t"];
const received = parts["v1"];
const expected = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
// Timing-safe comparison to prevent timing attacks
const a = Buffer.from(expected, "hex");
const b = Buffer.from(received, "hex");
if (a.length !== b.length) return false;
return crypto.timingSafeEqual(a, b);
}
// Next.js Route Handler example
export async function POST(req: Request) {
const rawBody = await req.text();
const sig = req.headers.get("x-tailorlabs-signature") ?? "";
if (!verifyTailorLabsSignature(rawBody, sig, process.env.WEBHOOK_SECRET!)) {
return new Response("Invalid signature", { status: 401 });
}
const event = JSON.parse(rawBody);
// handle event.event ...
return new Response("ok");
}Embeddable Badge
Every provider and certified AI agent has a TailorLabs Verified badge that can be embedded on any website. The badge is an iframe served from https://tailorlabs.io/badge/:providerId and is backed by the public GET /api/v1/scores endpoint.
iframe embed
<!-- Default badge (dark theme, 220×80px) -->
<iframe
src="https://tailorlabs.io/badge/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
width="220"
height="80"
frameborder="0"
scrolling="no"
title="TailorLabs Verified"
style="border:none; overflow:hidden;"
></iframe>Theme options
Append query params to customise the badge appearance:
| Param | Values | Default | Description |
|---|---|---|---|
theme | dark | light | dark | Badge background |
size | sm | md | lg | md | sm=160×60, md=220×80, lg=280×100 |
locale | en | fr | de | es | ja | en | Label language |
<!-- Light theme, large -->
<iframe
src="https://tailorlabs.io/badge/a1b2c3d4-...?theme=light&size=lg"
width="280"
height="100"
frameborder="0"
scrolling="no"
title="TailorLabs Verified"
style="border:none; overflow:hidden;"
></iframe>React / Next.js component
// TailorLabsBadge.tsx
interface TailorLabsBadgeProps {
providerId: string;
theme?: "dark" | "light";
size?: "sm" | "md" | "lg";
}
const DIMENSIONS = {
sm: { w: 160, h: 60 },
md: { w: 220, h: 80 },
lg: { w: 280, h: 100 },
};
export function TailorLabsBadge({
providerId,
theme = "dark",
size = "md",
}: TailorLabsBadgeProps) {
const { w, h } = DIMENSIONS[size];
const src = `https://tailorlabs.io/badge/${providerId}?theme=${theme}&size=${size}`;
return (
<iframe
src={src}
width={w}
height={h}
frameBorder={0}
scrolling="no"
title="TailorLabs Verified"
style={{ border: "none", overflow: "hidden" }}
/>
);
}Rate Limits
Rate limits are tracked per API key using a sliding window. Exceeded requests return HTTP 429 with a Retry-After header. Every response includes:
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1713090000The public GET /api/v1/scores/:providerId endpoint uses IP-based rate limiting — 60 requests per minute per IP, independent of API key.
Errors
All errors return a JSON object with an error string. Validation errors additionally return a details array with field-level messages.
// Validation error (422)
{
"error": "Validation failed",
"details": [
{ "field": "stake_percentage", "message": "Must be between 5 and 50" },
{ "field": "kpis", "message": "Weights must sum to 100. Got 90." }
]
}| Status | Name | Meaning |
|---|---|---|
400 | Bad Request | Malformed body or invalid field values |
401 | Unauthorized | Missing or invalid X-API-Key |
403 | Forbidden | Valid key but insufficient permissions |
404 | Not Found | Resource does not exist |
409 | Conflict | Duplicate resource (e.g. slug already taken) |
422 | Unprocessable | Validation failed — field errors returned in array |
429 | Too Many Requests | Rate limit exceeded |
500 | Server Error | Unexpected internal failure |
Questions? Email api@tailorlabs.io or open an issue in the partner portal.