openapi: 3.2.0 info: title: 2s — the (most) everything Pubsub API version: '1' summary: The (most) everything API. description: 'The (most) everything API for AI agents: 575+ pay-per-call endpoints on one origin.' contact: name: 2s url: https://2s.io email: alley@2s.io x-logo: url: https://2s.io/icon-512.png altText: 2s x-guidance: 'Pay-per-call REST API for AI agents — hundreds of endpoints returning ground-truth data (US public records, company & legal identifiers, finance/SEC, crypto/web3, security & CVEs, medical codes, weather & geocoding, agriculture, energy, maritime, music, and more). Every endpoint is paid per call in USDC via x402 (Base or Solana) — no API key, no signup. Call any endpoint with no auth to get a 402 PaymentRequirements envelope, sign it (EIP-3009 on Base, partial SPL transfer on Solana), and retry with the PAYMENT-SIGNATURE header. Add ?trial=1 for one free real call per endpoint per hour to test before paying. To discover the right endpoint: GET https://2s.io/api/directory for the full catalog, or GET https://2s.io/api/search/endpoints?q= for a ranked match. Per-call price is on each operation as x-payment-info (from $0.001). Batch up to 50 calls behind one payment via POST https://2s.io/api/batch/run.' servers: - url: https://2s.io tags: - name: Pubsub paths: /api/pubsub/create-topic: post: tags: - Pubsub summary: 'PUBSUB: create a topic you own, scoped to YOUR wallet' description: 'PUBSUB: create a topic you own, scoped to YOUR wallet. Returns a topicId — share it so other agents can pubsub.subscribe; only you (the owner) can pubsub.publish to it. The coordination backbone for multi-agent systems. Idempotent per name (re-creating returns the same id and extends its 90-day life). No account or API key — pay per call with x402.' operationId: pubsub_create-topic deprecated: false security: - x402Payment: [] responses: '200': description: 'Normalized: items = [the topic].' content: application/json: schema: type: object required: - data - meta properties: data: type: object properties: ok: type: boolean enum: - true items: type: array items: type: object properties: topicId: type: string name: type: string required: - topicId - name additionalProperties: false total: type: integer nullable: true description: Total matching rows upstream; null when unknown. source: $ref: '#/components/schemas/Source' required: - ok - items - total - source additionalProperties: false meta: $ref: '#/components/schemas/CallMeta' '400': $ref: '#/components/responses/BadRequest' '402': $ref: '#/components/responses/PaymentRequired' '405': $ref: '#/components/responses/MethodNotAllowed' '500': $ref: '#/components/responses/ServerError' '502': $ref: '#/components/responses/UpstreamError' x-2s-id: pubsub.create-topic x-2s-version: null x-2s-price: usd: 0.005 x-2s-accepts: - x402 x-2s-response-shape: normalized x-payment-info: price: mode: fixed currency: USD amount: '0.005000' protocols: - x402: {} requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: Topic name, 1-64 chars of [A-Za-z0-9._:-]. e.g. "price-alerts". required: - name additionalProperties: false parameters: - $ref: '#/components/parameters/TrialMode' /api/pubsub/publish: post: tags: - Pubsub summary: 'PUBSUB: publish a message to a topic YOU own, fanning out a' description: 'PUBSUB: publish a message to a topic YOU own, fanning out a signed callback to every CONFIRMED subscriber. Returns the number of subscribers it was delivered to. Only the topic owner (the x402 payer who created it) can publish. Message is arbitrary JSON (≤64 KB). Priced by confirmed-subscriber count (a small base + per subscriber), so you pay for the fan-out you request. Delivery is at-least-once with retry + signature.' operationId: pubsub_publish deprecated: false security: - x402Payment: [] responses: '200': description: 'Normalized: items = [{ delivered }] — subscriber count fanned to.' content: application/json: schema: type: object required: - data - meta properties: data: type: object properties: ok: type: boolean enum: - true items: type: array items: type: object properties: topicId: type: string delivered: type: number required: - topicId - delivered additionalProperties: false total: type: integer nullable: true description: Total matching rows upstream; null when unknown. source: $ref: '#/components/schemas/Source' required: - ok - items - total - source additionalProperties: false meta: $ref: '#/components/schemas/CallMeta' '400': $ref: '#/components/responses/BadRequest' '402': $ref: '#/components/responses/PaymentRequired' '405': $ref: '#/components/responses/MethodNotAllowed' '500': $ref: '#/components/responses/ServerError' '502': $ref: '#/components/responses/UpstreamError' x-2s-id: pubsub.publish x-2s-version: null x-2s-price: usd: 0.005 x-2s-accepts: - x402 x-2s-response-shape: normalized x-payment-info: price: mode: dynamic currency: USD min: '0.005000' max: '50.000000' protocols: - x402: {} requestBody: required: true content: application/json: schema: type: object properties: topicId: type: string description: The topic you own (from pubsub.create-topic). message: description: The payload to fan out — any JSON, up to 64 KB. required: - topicId additionalProperties: false parameters: - $ref: '#/components/parameters/TrialMode' /api/pubsub/subscribe: post: tags: - Pubsub summary: 'PUBSUB: subscribe a callbackUrl to a topic by its topicId' description: 'PUBSUB: subscribe a callbackUrl to a topic by its topicId (the topic can belong to any wallet — you just need the id). CONFIRMATION REQUIRED: we immediately POST a one-time challenge to your callbackUrl with header X-2s-Confirmation-Token (and {type:"2s_subscription_confirmation", token} in the JSON body); to be CONFIRMED your endpoint must reply 2xx with the response body set to exactly that token, or JSON {"token":""}. Only confirmed subscribers receive published messages (this prevents subscribing a non-consenting URL). Response field "confirmed" tells you if it worked; re-call to retry. When the owner publishes, we POST the message to your callbackUrl, EIP-191-signed (verify with X-2s-Signature) and retried with backoff; a subscriber that repeatedly fails delivery is auto-disabled. Returns a subscriptionId for pubsub.unsubscribe. Up to 100 subscribers per topic, one per URL. Pay per call with x402.' operationId: pubsub_subscribe deprecated: false security: - x402Payment: [] responses: '200': description: 'Normalized: items = [the subscription]. confirmed=false means your URL did not echo the challenge token; fix it and re-call.' content: application/json: schema: type: object required: - data - meta properties: data: type: object properties: ok: type: boolean enum: - true items: type: array items: type: object properties: subscriptionId: type: string confirmed: type: boolean callbackSigner: type: string required: - subscriptionId - confirmed - callbackSigner additionalProperties: false total: type: integer nullable: true description: Total matching rows upstream; null when unknown. source: $ref: '#/components/schemas/Source' required: - ok - items - total - source additionalProperties: false meta: $ref: '#/components/schemas/CallMeta' '400': $ref: '#/components/responses/BadRequest' '402': $ref: '#/components/responses/PaymentRequired' '405': $ref: '#/components/responses/MethodNotAllowed' '500': $ref: '#/components/responses/ServerError' '502': $ref: '#/components/responses/UpstreamError' x-2s-id: pubsub.subscribe x-2s-version: null x-2s-price: usd: 0.005 x-2s-accepts: - x402 x-2s-response-shape: normalized x-payment-info: price: mode: fixed currency: USD amount: '0.005000' protocols: - x402: {} requestBody: required: true content: application/json: schema: type: object properties: topicId: type: string description: The topicId to subscribe to (from pubsub.create-topic). callbackUrl: type: string format: uri maxLength: 2048 description: Where we POST published messages. Any http(s) URL; must echo the confirmation token to activate; body is signed. label: type: string maxLength: 64 description: Optional free-text tag. required: - topicId - callbackUrl additionalProperties: false parameters: - $ref: '#/components/parameters/TrialMode' /api/pubsub/unsubscribe: post: tags: - Pubsub summary: 'PUBSUB: remove one of YOUR subscriptions by its' description: 'PUBSUB: remove one of YOUR subscriptions by its subscriptionId — you stop receiving that topic''s messages. Returns removed:false if it isn''t yours or is already gone. Private to your wallet (the x402 payer).' operationId: pubsub_unsubscribe deprecated: false security: - x402Payment: [] responses: '200': description: 'Normalized: items = [the unsubscribe result].' content: application/json: schema: type: object required: - data - meta properties: data: type: object properties: ok: type: boolean enum: - true items: type: array items: type: object properties: subscriptionId: type: string removed: type: boolean required: - subscriptionId - removed additionalProperties: false total: type: integer nullable: true description: Total matching rows upstream; null when unknown. source: $ref: '#/components/schemas/Source' required: - ok - items - total - source additionalProperties: false meta: $ref: '#/components/schemas/CallMeta' '400': $ref: '#/components/responses/BadRequest' '402': $ref: '#/components/responses/PaymentRequired' '405': $ref: '#/components/responses/MethodNotAllowed' '500': $ref: '#/components/responses/ServerError' '502': $ref: '#/components/responses/UpstreamError' x-2s-id: pubsub.unsubscribe x-2s-version: null x-2s-price: usd: 0.005 x-2s-accepts: - x402 x-2s-response-shape: normalized x-payment-info: price: mode: fixed currency: USD amount: '0.005000' protocols: - x402: {} requestBody: required: true content: application/json: schema: type: object properties: subscriptionId: type: string description: The subscriptionId from pubsub.subscribe. required: - subscriptionId additionalProperties: false parameters: - $ref: '#/components/parameters/TrialMode' components: schemas: Source: type: object description: 'Provenance of the data: upstream provider, source URL, and license.' properties: provider: type: string description: Upstream data provider. url: type: string description: Source URL or documentation link. license: type: string description: License / usage terms for the data. CallMeta: type: object description: Per-call meta envelope — endpoint id, cost, caller kind, settlement details. X402PaymentRequiredV2: type: object description: x402 v2 PaymentRequired envelope. Pick any entry from accepts[], sign for that rail, retry with the PAYMENT-SIGNATURE header. required: - x402Version - accepts properties: x402Version: type: integer const: 2 error: type: string description: Human-readable reason payment is required. resource: type: string description: The resource URL being purchased. accepts: type: array description: Payment requirement options, one per supported network (Base USDC, Solana USDC). items: type: object required: - scheme - network - amount - asset - payTo - maxTimeoutSeconds properties: scheme: type: string enum: - exact network: type: string description: CAIP-2 network id, e.g. "eip155:8453" (Base) or "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp". amount: type: string description: Price in atomic asset units (USDC has 6 decimals). asset: type: string description: Asset contract address / mint. payTo: type: string description: Treasury address to pay. maxTimeoutSeconds: type: integer extra: type: object description: 'Rail-specific extras (EVM: EIP-712 domain name/version; Solana: feePayer).' additionalProperties: true extensions: type: object description: Optional discovery metadata (e.g. bazaar input/output schemas). additionalProperties: true responses: PaymentRequired: description: Payment required. Body contains the x402 PaymentRequirements envelope with a multi-network accepts array; the per-call price is in accepts[].amount (and on the operation as x-2s-price). Sign for whichever rail you hold USDC on (EIP-3009 for Base, partial SPL transfer for Solana) and retry with the PAYMENT-SIGNATURE header (X-PAYMENT also accepted for v1 clients). content: application/json: schema: $ref: '#/components/schemas/X402PaymentRequiredV2' UpstreamError: description: Upstream provider error. MethodNotAllowed: description: Method not allowed — see `Allow` header for the supported method. ServerError: description: Internal server error. BadRequest: description: Bad request — invalid parameters. parameters: TrialMode: name: trial in: query required: false description: 'Try before you buy. Set to 1 for one free real call per endpoint per hour — no wallet or payment needed — to verify the endpoint before paying. Equivalent to sending the "X-2s-Trial: 1" request header. Works on every endpoint.' schema: type: integer enum: - 1 securitySchemes: x402Payment: type: apiKey in: header name: PAYMENT-SIGNATURE description: 'x402 protocol v2: base64-encoded PaymentPayload. Call any paid endpoint without auth to receive a 402 with a multi-network PaymentRequirements envelope. Sign for either rail: EIP-3009 transferWithAuthorization (Base USDC) OR a partial SPL token transfer (Solana USDC). Retry with PAYMENT-SIGNATURE header. X-PAYMENT is also accepted for v1 buyer clients. See https://x402.org.'