{"openapi": "3.0.3", "info": {"title": "Harbor pilots for agents", "version": "0.1.0", "description": "Pilot capsule registry + A2A-shaped boarding with Ed25519 traversal-receipt certification and visit-only authority slices. Provider: TextForAgents LLC. Support: support@textforagents.com"}, "paths": {"/": {"get": {"summary": "Public product descriptor", "responses": {"200": {"description": "Descriptor", "content": {"application/json": {"schema": {"type": "object", "properties": {"product": {"type": "string"}}, "required": []}}}}}}}, "/health": {"get": {"summary": "Health", "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"type": "object", "properties": {"status": {"type": "string"}}, "required": []}}}}}}}, "/register": {"post": {"summary": "Register an account", "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"account_name": {"type": "string"}, "payer_wallet": {"type": "string"}}, "required": ["account_name", "payer_wallet"]}}}}, "responses": {"200": {"description": "Account + claim token", "content": {"application/json": {"schema": {"type": "object", "properties": {"account_id": {"type": "string"}, "claim_token": {"type": "string"}}, "required": []}}}}}}}, "/trial": {"post": {"summary": "Claim the one-time trial (10 free boardings)", "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"account_id": {"type": "string"}, "claim_token": {"type": "string"}}, "required": ["account_id", "claim_token"]}}}}, "responses": {"200": {"description": "Trial token (shown once)", "content": {"application/json": {"schema": {"type": "object", "properties": {"token": {"type": "string"}, "tier": {"type": "string"}, "trial_boardings": {"type": "integer"}}, "required": []}}}}, "403": {"description": "Trial already used or bad claim"}}}}, "/payg-token": {"post": {"summary": "Issue a pay-per-boarding token", "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"account_id": {"type": "string"}, "claim_token": {"type": "string"}}, "required": ["account_id", "claim_token"]}}}}, "responses": {"200": {"description": "PayPerCall token (shown once)", "content": {"application/json": {"schema": {"type": "object", "properties": {"token": {"type": "string"}, "tier": {"type": "string"}}, "required": []}}}}}}}, "/subscribe": {"post": {"summary": "Subscribe Fleet via x402 ($19 = 19000000 atomic USDC)", "parameters": [{"name": "X-PAYMENT", "in": "header", "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"account_id": {"type": "string"}, "tier": {"type": "string"}}, "required": ["account_id", "tier"]}}}}, "responses": {"200": {"description": "Fleet token, 30 days, 200 boardings included", "content": {"application/json": {"schema": {"type": "object", "properties": {"token": {"type": "string"}, "tier": {"type": "string"}, "expires_at": {"type": "number"}}, "required": []}}}}, "402": {"description": "x402 payment required / payment rejected"}}}}, "/board": {"post": {"summary": "Board a harbor: issue a visit-only authority slice. Consumes a trial credit, a Fleet-included boarding, or an x402 payment of $0.10 (X-PAYMENT header).", "security": [{"BearerAuth": []}], "parameters": [{"name": "X-PAYMENT", "in": "header", "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"harbor_id": {"type": "string"}, "task": {"type": "string"}}, "required": ["harbor_id", "task"]}}}}, "responses": {"200": {"description": "Slice issued", "content": {"application/json": {"schema": {"type": "object", "properties": {"slice": {"type": "object", "properties": {"slice_id": {"type": "string"}, "visitor": {"type": "string"}, "harbor": {"type": "string"}, "task": {"type": "string"}, "capsule_version": {"type": "integer"}, "issued": {"type": "number"}, "expires": {"type": "number"}, "max_uses": {"type": "integer"}, "uses": {"type": "integer"}, "revoked": {"type": "boolean"}, "sig": {"type": "string"}}, "required": ["slice_id", "visitor", "harbor", "task", "sig"]}, "boarding": {"type": "string"}}, "required": []}}}}, "401": {"description": "Missing/expired token"}, "402": {"description": "x402 payment required / payment rejected"}, "409": {"description": "Harbor not CERTIFIED"}}}}, "/fetch-capsule": {"post": {"summary": "Fetch the capsule against a valid slice (single use)", "security": [{"BearerAuth": []}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"slice": {"type": "object", "properties": {"slice_id": {"type": "string"}, "visitor": {"type": "string"}, "harbor": {"type": "string"}, "task": {"type": "string"}, "capsule_version": {"type": "integer"}, "issued": {"type": "number"}, "expires": {"type": "number"}, "max_uses": {"type": "integer"}, "uses": {"type": "integer"}, "revoked": {"type": "boolean"}, "sig": {"type": "string"}}, "required": ["slice_id", "visitor", "harbor", "task", "sig"]}}, "required": ["slice"]}}}}, "responses": {"200": {"description": "Capsule", "content": {"application/json": {"schema": {"type": "object", "properties": {"capsule": {"type": "object", "properties": {"harbor": {"type": "string"}, "version": {"type": "integer"}, "entry": {"type": "string"}, "encoding": {"type": "string"}, "header": {"type": "array", "items": {"type": "string"}, "nullable": true}, "sounding": {"type": "boolean"}, "confirm": {"type": "boolean"}}, "required": []}}, "required": []}}}}, "401": {"description": "Missing/expired token"}, "403": {"description": "Slice invalid, expired, used, or bound to another visitor"}}}}, "/demo/{harbor}": {"get": {"summary": "Demo harbor home through the public proxy: returns the harbor's entry links. Authenticated; traversal steps are bound to your boarding slice.", "security": [{"BearerAuth": []}], "parameters": [{"name": "harbor", "in": "path", "required": true, "schema": {"type": "string", "enum": ["alpha", "beta", "gamma", "delta", "epsilon"]}}], "responses": {"200": {"description": "Harbor links"}, "401": {"description": "Missing/expired token"}}}}, "/demo/{harbor}/{traversal_path}": {"get": {"summary": "Demo harbor traversal GET through the public proxy (only /soundings is defined; t = the step token from the entry step). The session must belong to your account.", "security": [{"BearerAuth": []}], "parameters": [{"name": "harbor", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "traversal_path", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "t", "in": "query", "schema": {"type": "string"}}], "responses": {"200": {"description": "Harbor response"}, "403": {"description": "Session belongs to another account or is unknown"}, "404": {"description": "Path is not a demo-harbor traversal path"}}}, "post": {"summary": "Demo harbor traversal POST through the public proxy. traversal_path is the capsule entry (e.g. quay/start) or step2, commit, or confirm. Entry calls must name a task you hold an unexpired, unrevoked boarding slice for; the vessel is forced to your account_id. Step calls must carry the step token of a session owned by your account. Body encoding and quirk header exactly as the capsule states (form or json).", "security": [{"BearerAuth": []}], "parameters": [{"name": "harbor", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "traversal_path", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Harbor response (step token + next step)"}, "400": {"description": "Harbor rejected the step (wrong encoding/header/fields) or bad request"}, "403": {"description": "No active boarding slice for this harbor+task, or the session belongs to another account"}, "404": {"description": "Path is not a demo-harbor traversal path"}}}}, "/demo/{harbor}/receipt": {"post": {"summary": "Demo harbors only: harbor-signed traversal receipt for an observed traversal by the caller (vessel = your account_id)", "security": [{"BearerAuth": []}], "parameters": [{"name": "harbor", "in": "path", "required": true, "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"task": {"type": "string"}, "capsule_version": {"type": "integer"}, "nonce": {"type": "string"}, "success": {"type": "boolean"}}, "required": ["task", "capsule_version", "nonce", "success"]}}}}, "responses": {"200": {"description": "Signed receipt", "content": {"application/json": {"schema": {"type": "object", "properties": {"receipt": {"type": "object", "properties": {"harbor": {"type": "string"}, "visitor": {"type": "string"}, "task": {"type": "string"}, "success": {"type": "boolean"}, "capsule_version": {"type": "integer"}, "nonce": {"type": "string"}, "ts": {"type": "number"}, "sig": {"type": "string"}}, "required": ["harbor", "visitor", "task", "success", "capsule_version", "nonce", "sig"]}}, "required": []}}}}, "409": {"description": "Traversal not attested by the harbor"}}}}, "/complete": {"post": {"summary": "Complete a visit: submit the harbor-signed receipt; the slice auto-revokes", "security": [{"BearerAuth": []}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"slice_id": {"type": "string"}, "receipt": {"type": "object", "properties": {"harbor": {"type": "string"}, "visitor": {"type": "string"}, "task": {"type": "string"}, "success": {"type": "boolean"}, "capsule_version": {"type": "integer"}, "nonce": {"type": "string"}, "ts": {"type": "number"}, "sig": {"type": "string"}}, "required": ["harbor", "visitor", "task", "success", "capsule_version", "nonce", "sig"]}}, "required": ["slice_id", "receipt"]}}}}, "responses": {"200": {"description": "Receipt recorded; certification state returned", "content": {"application/json": {"schema": {"type": "object", "properties": {"accepted": {"type": "boolean"}, "certification": {"type": "string"}}, "required": []}}}}, "401": {"description": "Missing/expired token"}, "403": {"description": "Slice belongs to another account or receipt rejected"}}}}, "/harbors": {"get": {"summary": "Demo harbors + certification states", "security": [{"BearerAuth": []}], "responses": {"200": {"description": "Harbors", "content": {"application/json": {"schema": {"type": "object", "properties": {"harbors": {"type": "array", "items": {"type": "object"}}}, "required": []}}}}, "401": {"description": "Missing/expired token"}}}}, "/account": {"get": {"summary": "Caller's account state: tier, trial credits, Fleet usage, share-ledger totals", "security": [{"BearerAuth": []}], "responses": {"200": {"description": "Account state", "content": {"application/json": {"schema": {"type": "object", "properties": {"account_id": {"type": "string"}, "tier": {"type": "string"}, "trial_credits": {"type": "integer"}}, "required": []}}}}, "401": {"description": "Missing/expired token"}}}}, "/mcp": {"post": {"summary": "MCP streamable-http endpoint (JSON-RPC: initialize, ping, tools/list, tools/call; also served at POST / when the body is JSON-RPC)", "security": [{"BearerAuth": []}], "responses": {"200": {"description": "JSON-RPC response"}, "401": {"description": "unauthorized; body names the issuance path"}, "202": {"description": "notification accepted (notifications/initialized)"}}}}, "/tokens/revoke": {"post": {"summary": "Revoke the caller's token", "security": [{"BearerAuth": []}], "responses": {"200": {"description": "Revoked", "content": {"application/json": {"schema": {"type": "object", "properties": {"revoked": {"type": "boolean"}}, "required": []}}}}}}}}, "components": {"securitySchemes": {"BearerAuth": {"type": "http", "scheme": "bearer"}}, "schemas": {"Slice": {"type": "object", "properties": {"slice_id": {"type": "string"}, "visitor": {"type": "string"}, "harbor": {"type": "string"}, "task": {"type": "string"}, "capsule_version": {"type": "integer"}, "issued": {"type": "number"}, "expires": {"type": "number"}, "max_uses": {"type": "integer"}, "uses": {"type": "integer"}, "revoked": {"type": "boolean"}, "sig": {"type": "string"}}, "required": ["slice_id", "visitor", "harbor", "task", "sig"]}, "Capsule": {"type": "object", "properties": {"harbor": {"type": "string"}, "version": {"type": "integer"}, "entry": {"type": "string"}, "encoding": {"type": "string"}, "header": {"type": "array", "items": {"type": "string"}, "nullable": true}, "sounding": {"type": "boolean"}, "confirm": {"type": "boolean"}}, "required": []}, "Receipt": {"type": "object", "properties": {"harbor": {"type": "string"}, "visitor": {"type": "string"}, "task": {"type": "string"}, "success": {"type": "boolean"}, "capsule_version": {"type": "integer"}, "nonce": {"type": "string"}, "ts": {"type": "number"}, "sig": {"type": "string"}}, "required": ["harbor", "visitor", "task", "success", "capsule_version", "nonce", "sig"]}}}}