{"openapi":"3.1.0","info":{"title":"AIPI — Agent Intelligence Platform","version":"2.0.0","description":"AI search visibility intelligence for B2B SaaS. The public surface ships the GEO pillar only — citation tracking across ChatGPT, Claude, Gemini, Perplexity. Managed-service / internal-tier customers can opt in to the full intelligence set (SEO, AIO, AEO, SXO, UNIFIED) via /api/v2/agents/capabilities/internal.","contact":{"name":"Analytical Insider","url":"https://analyticalinsider.ai"}},"servers":[{"url":"https://agents.analyticalinsider.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"AIPI API key"},"X402Payment":{"type":"apiKey","in":"header","name":"X-Payment","description":"x402 micropayment on Base"}},"schemas":{"DsrRequestBody":{"type":"object","required":["subjectId","legalBasis"],"properties":{"subjectId":{"type":"string","description":"The data subject identifier (email, user id, etc.). Hashed before storage."},"subjectIdKind":{"type":"string","description":"Identifier kind — email, user_id, api_key_id, etc.","default":"email"},"legalBasis":{"type":"string","description":"The legal basis asserted by the submitter."}}},"AnalyzeRequest":{"type":"object","required":["subject"],"properties":{"subject":{"type":"object","required":["domain"],"properties":{"domain":{"type":"string","example":"timeliner.io","description":"Domain to analyze (no https://)."},"brandName":{"type":"string","example":"Timeliner","description":"Brand name for GEO citation matching. Strongly recommended."},"industry":{"type":"string","example":"video production software"},"targetKeywords":{"type":"array","items":{"type":"string"}},"competitors":{"type":"array","items":{"type":"string"},"example":["frame.io","air.inc"]}}},"pillars":{"type":"array","items":{"type":"string","enum":["GEO"]},"description":"Pillars to run. Public surface: GEO only. Omitting defaults to [\"GEO\"]. Internal-tier callers may request additional pillars via /api/v2/agents/capabilities/internal.","example":["GEO"]},"geoProfileId":{"type":"string","description":"Optional: tie analysis to an existing GEO profile for historical tracking."},"includeRecommendations":{"type":"boolean","default":true},"includeCompetitors":{"type":"boolean","default":false}}},"ReceiptSubmission":{"type":"object","required":["receipt","callerSignature"],"properties":{"receipt":{"type":"object","required":["callerPubKey","calleeAgentUrl","capability","outcome","latencyMs","startedAt","completedAt"],"properties":{"callerPubKey":{"type":"string","description":"base64-encoded ed25519 public key of the caller."},"calleeAgentUrl":{"type":"string","format":"uri","description":"Canonical URL of the remote (callee) agent."},"capability":{"type":"string","description":"Capability slug invoked on the callee, e.g. \"search.web\"."},"outcome":{"type":"string","enum":["success","failure","partial"]},"latencyMs":{"type":"integer","minimum":0},"startedAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","format":"date-time"},"receiptBody":{"type":"object","description":"Free-form JSON body the caller signs. JCS-canonicalized for signature input."},"disputed":{"type":"boolean","default":false},"disputeReason":{"type":"string"}}},"callerSignature":{"type":"string","description":"base64url-encoded ed25519 signature over JCS(receipt body), produced by callerPubKey."}}},"ProbeRequest":{"type":"object","required":["agentUrl"],"properties":{"agentUrl":{"type":"string","format":"uri","description":"URL of the remote A2A agent to probe."},"forceRefresh":{"type":"boolean","default":false,"description":"Bypass the agent-card cache and re-fetch."}}},"ReputationSnapshot":{"type":"object","properties":{"agentUrl":{"type":"string","format":"uri"},"windowStart":{"type":"string","format":"date-time"},"windowEnd":{"type":"string","format":"date-time"},"sampleSize":{"type":"integer","minimum":0},"successRate":{"type":"number","minimum":0,"maximum":1},"failureRate":{"type":"number","minimum":0,"maximum":1},"partialRate":{"type":"number","minimum":0,"maximum":1},"disputeRate":{"type":"number","minimum":0,"maximum":1},"p50LatencyMs":{"type":"number"},"p95LatencyMs":{"type":"number"},"p99LatencyMs":{"type":"number"},"lowConfidence":{"type":"boolean","description":"True until sampleSize crosses MIN_SAMPLE_FOR_CONFIDENCE."},"capability":{"type":["string","null"]}}},"KnowledgeGraphEdges":{"type":"object","properties":{"edges":{"type":"array","items":{"type":"object","properties":{"edgeId":{"type":"string"},"edgeType":{"type":"string","enum":["CITES","RANKS_FOR","MENTIONS","COMPETES_WITH","REFERENCED_BY"]},"sourceNodeId":{"type":"string"},"targetNodeId":{"type":"string"},"weight":{"type":"number"},"metadata":{"type":"object"}}}},"totalEdges":{"type":"integer"}}},"MonitoringSubscription":{"type":"object","required":["url","callbackUrl"],"properties":{"url":{"type":"string","format":"uri"},"callbackUrl":{"type":"string","format":"uri","description":"HTTPS webhook endpoint on your agent."},"pillars":{"type":"array","items":{"type":"string","enum":["GEO"]},"description":"Pillars to monitor. Public surface: GEO only."}}}}},"paths":{"/.well-known/agent-card.json":{"get":{"operationId":"getAgentCard","summary":"A2A v1.2 Signed Agent Card","description":"aipi self-description: pillars, trust primitives (probe/receipts/reputation), supported transports. Includes a JWS detached-payload ed25519 signature over the JCS canonicalization of the card body. Verifiers look up the signing key via kid at /.well-known/aipi-signing-keys.json. The legacy path /.well-known/agent.json serves the identical body for A2A v1.0 clients.","security":[],"responses":{"200":{"description":"Signed Agent Card","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/v2/health":{"get":{"operationId":"getHealth","summary":"Service health","security":[],"responses":{"200":{"description":"Service is healthy"}}}},"/status":{"get":{"operationId":"getStatus","summary":"Public status — components, SLO burn, active incidents","description":"Public, unauthenticated status endpoint for external monitors and customer status-page pollers. Returns component-level liveness (api/db/redis), a rolling-30d SLO burn value (null until wired), and the active-incident slug list. Never exposes infrastructure details, tenant data, or secret material.","security":[],"responses":{"200":{"description":"Public status payload"}}}},"/api/v2/privacy/access-request":{"post":{"operationId":"privacyAccessRequest","summary":"GDPR Art. 15 / CCPA §1798.100 — data subject access request","description":"Submit a data subject access request. aipi issues an ed25519-signed receipt the submitter can present to regulators as proof of submission. The subject identifier is hashed — raw identifiers never persist.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["subjectId","legalBasis"],"properties":{"subjectId":{"type":"string","description":"The data subject identifier (email, user id, etc.). Hashed before storage."},"subjectIdKind":{"type":"string","description":"Identifier kind — email, user_id, api_key_id, etc.","default":"email"},"legalBasis":{"type":"string","description":"The legal basis asserted by the submitter."}}}}}},"responses":{"201":{"description":"Witness-signed DSR receipt"},"503":{"description":"Witness signer unavailable — no row persisted"}}}},"/api/v2/privacy/delete-request":{"post":{"operationId":"privacyDeleteRequest","summary":"GDPR Art. 17 / CCPA §1798.105 — data subject deletion request","description":"Submit a data subject deletion request. Returns a witness-signed receipt. Fulfillment (the actual deletion) is handled asynchronously — see docs/compliance/DSR_RUNBOOK.md.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DsrRequestBody"}}}},"responses":{"201":{"description":"Witness-signed DSR receipt"},"503":{"description":"Witness signer unavailable — no row persisted"}}}},"/api/v2/privacy/consent-revocation":{"post":{"operationId":"privacyConsentRevocation","summary":"GDPR Art. 7(3) / CCPA §1798.120 — consent revocation","description":"Revoke previously-granted consent. Returns a witness-signed receipt attesting the revocation request was received.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DsrRequestBody"}}}},"responses":{"201":{"description":"Witness-signed DSR receipt"},"503":{"description":"Witness signer unavailable — no row persisted"}}}},"/api/v2/agents/capabilities":{"get":{"operationId":"getCapabilities","summary":"List registered intelligence agents and their capabilities","security":[],"responses":{"200":{"description":"Agent capabilities list"}}}},"/api/v2/agents/hatch":{"post":{"operationId":"hatchAgent","summary":"Self-register to receive a Bearer API key (no account required)","description":"One-call registration. POST your agentUrl and agentName to receive an apiKey. Use that apiKey as the Bearer token for all subsequent calls. Idempotent — re-registering the same agentUrl returns the same key.\n\nMVP Phase 2 (2026-04-26): an optional `cohortCode` may be supplied to redeem an invite-only cohort (COHORT_0/1/2). The cohort is encoded into the returned API key and surfaces on each request as `request.cohort` for per-route gating. Omitting `cohortCode` mints a public-cohort key.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["agentUrl"],"properties":{"agentUrl":{"type":"string","format":"uri","example":"https://your-agent.example.com","description":"The canonical URL of your agent or website. Used to derive your orgId."},"agentName":{"type":"string","example":"My Agent","description":"Human-readable name for your agent."},"termsAccepted":{"type":"boolean","default":true},"cohortCode":{"type":"string","minLength":4,"maxLength":64,"description":"Optional invite code. When supplied, the code is atomically redeemed against the InviteCode store and the resulting cohort is stamped onto the minted API key. 404/409/410 are returned for unknown / already-redeemed / expired codes respectively."}}}}}},"responses":{"200":{"description":"Registration successful","content":{"application/json":{"schema":{"type":"object","properties":{"registered":{"type":"boolean"},"agentId":{"type":"string"},"orgId":{"type":"string"},"agentName":{"type":"string"},"apiKey":{"type":"string","description":"Use as: Authorization: Bearer <apiKey>"},"tier":{"type":"string","example":"T1"},"cohort":{"type":"string","example":"PUBLIC","description":"PUBLIC for non-invited callers; COHORT_0/1/2 if cohortCode was supplied and redeemed."}}}}}},"404":{"description":"Unknown invite code (INVITE_CODE_NOT_FOUND)"},"409":{"description":"Invite code has already been redeemed (INVITE_CODE_ALREADY_REDEEMED)"},"410":{"description":"Invite code has expired (INVITE_CODE_EXPIRED)"}}}},"/api/v2/waitlist/signup":{"post":{"operationId":"signupForWaitlist","summary":"Join the AiPi launch waitlist","description":"Capture an email + 3 qualifier answers ahead of the C1 cohort opening. Unauthenticated by design (no API key required). Idempotent on the email address — re-submitting overwrites qualifier answers but preserves first-touch UTM attribution. utm_source / utm_medium are read from the URL query string when present, otherwise from the request body.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email","maxLength":254},"primaryGoal":{"type":"string","maxLength":2000,"description":"Free-text answer to the \"what are you trying to do\" qualifier."},"monthlyContent":{"type":"string","maxLength":2000,"description":"Free-text answer to the content-volume qualifier."},"hasTriedGeo":{"type":"boolean","description":"Whether the prospect has previously tried generative-engine optimization tools."},"utmSource":{"type":"string","maxLength":120},"utmMedium":{"type":"string","maxLength":120}}}}}},"responses":{"201":{"description":"Signup persisted; first-touch UTM stored."},"202":{"description":"Signup accepted but not persisted (deploy-window degradation; see degraded:true)."},"400":{"description":"Invalid body (VALIDATION_ERROR)."}}}},"/api/v2/score":{"post":{"operationId":"runScorecard","summary":"Single-domain GEO scorecard with up to 3 manual competitors","description":"Phase 2 scorecard endpoint. Pass a domain plus up to 3 optional competitor1/competitor2/competitor3 fields; the route fans out a GEO analysis for the primary subject and (in parallel) for each competitor with an 8-second per-competitor timeout. The primary report is returned in the same shape as /api/v2/intelligence/analyze plus a `competitors` array carrying `{domain, status, overallScore, error?}` per competitor.","security":[{"BearerAuth":[]},{"X402Payment":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["domain"],"properties":{"domain":{"type":"string","minLength":1,"maxLength":253,"example":"analyticalinsider.ai"},"brandName":{"type":"string","minLength":1,"maxLength":120},"industry":{"type":"string","minLength":1,"maxLength":120},"targetKeywords":{"type":"array","items":{"type":"string","minLength":1,"maxLength":120},"maxItems":8},"competitor1":{"type":"string","minLength":1,"maxLength":253},"competitor2":{"type":"string","minLength":1,"maxLength":253},"competitor3":{"type":"string","minLength":1,"maxLength":253}}}}}},"responses":{"200":{"description":"Scorecard with primary + 0..3 competitor outcomes."},"400":{"description":"Invalid body (VALIDATION_ERROR)."},"500":{"description":"Primary scoring failed (PRIMARY_FAILED) — competitor failures do NOT trigger 5xx; they surface as status=\"failed\" entries in the response."}}}},"/api/v2/intelligence/analyze/stream":{"post":{"operationId":"streamAnalysis","summary":"Stream GEO intelligence analysis via Server-Sent Events","description":"Same as /analyze but streams results in real-time as the GEO pillar completes. Response is text/event-stream. Events: started, pillar_complete, pillar_error, complete, trial_exhausted, error. Recommended for human-facing clients or any caller that wants live progress feedback.","security":[{"BearerAuth":[]},{"X402Payment":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyzeRequest"}}}},"responses":{"200":{"description":"SSE stream of pillar results. Content-Type: text/event-stream"},"400":{"description":"Invalid request body or unsupported pillars on the public surface (only [\"GEO\"] is allowed for public-tier callers)"},"401":{"description":"API key required"},"402":{"description":"x402 payment required"}}}},"/api/v2/intelligence/analyze":{"post":{"operationId":"runAnalysis","summary":"Run GEO intelligence analysis for a domain","description":"Returns the GEO citation visibility score and recommendations for the supplied domain. Requires a Bearer key from /api/v2/agents/hatch, or an x402 payment ($0.25 USDC). subject.domain is required; brandName is strongly recommended for accurate GEO citation matching. Public-tier callers must pass pillars: [\"GEO\"] (or omit pillars to default to [\"GEO\"]); requesting other pillars on the public tier returns 400. Internal-tier callers can request the full 5-pillar set — see /api/v2/agents/capabilities/internal.\n\nResponses include the canonical `citation_position_score` metric. The legacy `citation_position_avg` alias is also emitted for backwards compatibility (Q-Greg-4 ruling, 2026-04-26) — both fields carry the same value, the response carries `Deprecation: true` and a `Sunset` date 60 days out, and consumers should migrate before the sunset window closes.","security":[{"BearerAuth":[]},{"X402Payment":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyzeRequest"}}}},"responses":{"200":{"description":"Intelligence analysis results. May include Deprecation/Sunset headers when the response payload still contains the legacy citation_position_avg alias."},"400":{"description":"Invalid request body or unsupported pillars on the public surface"},"401":{"description":"API key required — call /api/v2/agents/hatch first"},"402":{"description":"x402 payment required"}}}},"/api/v2/agents/probe":{"post":{"operationId":"probeRemoteAgent","summary":"Probe a remote agent and return cached card metadata + trustTier","description":"Fetch the remote agent's .well-known/agent.json card, parse capabilities, and return an aipi-computed trustTier (T0–T4). Idempotent at the cache layer.","security":[{"BearerAuth":[]},{"X402Payment":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProbeRequest"}}}},"responses":{"200":{"description":"Probe result with parsed card and trustTier"},"400":{"description":"Invalid agentUrl"},"401":{"description":"API key required"},"402":{"description":"x402 payment required"}}}},"/api/v2/agents/receipts":{"post":{"operationId":"submitReceipt","summary":"Submit a caller-signed agent-to-agent receipt for witnessing","description":"Caller signs a receipt body with their ed25519 private key, posts it here, aipi verifies the caller signature and attaches a witness signature (aipi-witness-v1). Idempotent on receipt-hash. The full request body schema is in components.schemas.ReceiptSubmission.","security":[{"BearerAuth":[]},{"X402Payment":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceiptSubmission"}}}},"responses":{"200":{"description":"Idempotent replay — receipt was already witnessed"},"201":{"description":"Receipt witnessed and stored"},"400":{"description":"Invalid caller signature"},"401":{"description":"API key required"},"402":{"description":"x402 payment required"},"503":{"description":"Witness signer unavailable — no row persisted"}}}},"/api/v2/agents/{encodedAgentUrl}/reputation":{"get":{"operationId":"getAgentReputation","summary":"Compute a remote agent's reputation snapshot from witnessed receipts","description":"Returns success / failure / partial / dispute rates, latency p50/p95/p99, sample size, and a low-confidence flag. The path segment {encodedAgentUrl} MUST be base64url-encoded (RFC 4648 §5, no padding). URL-encoding does NOT work — that is the source of the 04-23 audit's most common caller mistake.","security":[{"BearerAuth":[]},{"X402Payment":[]}],"parameters":[{"name":"encodedAgentUrl","in":"path","required":true,"schema":{"type":"string"},"description":"Agent URL encoded as base64url (RFC 4648 §5, no padding). Example: agentUrl=\"https://agents.example.com\" → encodedAgentUrl=\"aHR0cHM6Ly9hZ2VudHMuZXhhbXBsZS5jb20\". In Node: Buffer.from(agentUrl).toString(\"base64url\").","example":"aHR0cHM6Ly9hZ2VudHMuZXhhbXBsZS5jb20"},{"name":"windowDays","in":"query","schema":{"type":"integer","minimum":1,"maximum":365},"description":"Window for the rolling computation. Defaults to the server-side default (30d)."},{"name":"capability","in":"query","schema":{"type":"string","minLength":1,"maxLength":200},"description":"Filter receipts to a single capability slug, e.g. \"search.web\"."}],"responses":{"200":{"description":"Reputation snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReputationSnapshot"}}}},"400":{"description":"encodedAgentUrl is not valid base64url"},"401":{"description":"API key required"},"402":{"description":"x402 payment required"}}}},"/api/v2/intelligence/cycle/{cycleId}":{"delete":{"operationId":"cancelIntelligenceCycle","summary":"Cancel an in-flight intelligence cycle","description":"Cancels an orchestration cycle started by /analyze or /analyze/stream. In-flight agent steps finish their current LLM call; no new steps start. Returns 204 when the cycle was found and aborted, 404 when the cycleId is unknown (never existed or already completed).","security":[{"BearerAuth":[]}],"parameters":[{"name":"cycleId","in":"path","required":true,"schema":{"type":"string"},"description":"The cycleId returned in the /analyze response body or in the SSE `complete` event."}],"responses":{"204":{"description":"Cancellation signalled. In-flight steps finish; no new steps start (< 2s)."},"400":{"description":"Invalid cycleId"},"401":{"description":"API key required"},"404":{"description":"Cycle not found (unknown id or already completed)."}}}},"/api/v2/intelligence/knowledge-graph/edges":{"get":{"operationId":"queryKnowledgeGraphEdges","summary":"Query edges in the AI citation knowledge graph by source OR target node","description":"Provide exactly one of `sourceNodeId` or `targetNodeId`. Returns edges filtered by optional `edgeType` and limited to `limit` results (default 100, max 500).","security":[{"BearerAuth":[]},{"X402Payment":[]}],"parameters":[{"name":"sourceNodeId","in":"query","schema":{"type":"string"},"description":"Outbound edges from this node. Mutually exclusive with targetNodeId."},{"name":"targetNodeId","in":"query","schema":{"type":"string"},"description":"Inbound edges into this node. Mutually exclusive with sourceNodeId."},{"name":"edgeType","in":"query","schema":{"type":"string","enum":["CITES","RANKS_FOR","MENTIONS","COMPETES_WITH","REFERENCED_BY"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500,"default":100}}],"responses":{"200":{"description":"Knowledge graph edges","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeGraphEdges"}}}},"400":{"description":"Missing or invalid query parameters"},"401":{"description":"API key required"}}}},"/api/v2/monitoring/subscriptions":{"post":{"operationId":"createSubscription","summary":"Subscribe to real-time GEO monitoring for a URL","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitoringSubscription"}}}},"responses":{"201":{"description":"Subscription created"},"400":{"description":"Invalid subscription payload"},"401":{"description":"API key required"}}}}}}