openapi: 3.2.0 info: title: 2s — the (most) everything Property 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: property paths: /api/property/nyc-deed-history: get: tags: - property summary: NYC deed + mortgage history for a tax lot via ACRIS description: 'NYC deed + mortgage history for a tax lot via ACRIS (Automated City Register Information System) legals dataset, keyed by BBL. Each row carries a unique documentId you can use to drill into the ACRIS master dataset (the master URL pattern is included in the response) for full details: parties, consideration amount, document type (DEED, MORTGAGE, ASSIGNMENT OF MORTGAGE, etc.). Use `property.nyc-parcel-lookup` first to convert an address to a BBL. Returns most-recent records first.' operationId: property_nyc-deed-history deprecated: false security: - x402Payment: [] responses: '200': description: 'Normalized envelope: items = ACRIS legals records for the BBL.' 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: documentId: type: string description: ACRIS document id — drill into the master dataset (meta.masterDatasetForDocIds) for parties, amounts, doc type. recordType: type: string nullable: true borough: type: number description: 1=Manhattan, 2=Bronx, 3=Brooklyn, 4=Queens, 5=Staten Island. block: type: number lot: type: number propertyType: type: string nullable: true goodThroughDate: type: string nullable: true required: - documentId - recordType - borough - block - lot - propertyType - goodThroughDate additionalProperties: false total: type: integer nullable: true description: Total matching rows upstream; null when unknown. source: $ref: '#/components/schemas/Source' meta: type: object properties: bbl: type: string masterDatasetForDocIds: type: string required: - bbl - masterDatasetForDocIds additionalProperties: false 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: property.nyc-deed-history x-2s-version: null x-2s-price: usd: 0.003 x-2s-accepts: - x402 x-2s-response-shape: normalized x-payment-info: price: mode: fixed currency: USD amount: '0.003000' protocols: - x402: {} parameters: - name: bbl in: query required: true description: Bbl. schema: type: string pattern: ^[1-5][- 0-9]{9,19}$ - name: limit in: query required: false description: Maximum number of results to return. schema: type: integer minimum: 1 maximum: 200 default: 25 - name: offset in: query required: false description: Number of results to skip before returning (pagination offset). schema: type: integer minimum: 0 default: 0 - $ref: '#/components/parameters/TrialMode' /api/property/nyc-parcel-lookup: get: tags: - property summary: NYC tax-lot lookup via PLUTO (Primary Land Use Tax Lot description: NYC tax-lot lookup via PLUTO (Primary Land Use Tax Lot Output) — every tax lot in the city with owner, zoning, lot/building area, year built, classification, lat/lon, community + school + council + police districts. Pass `bbl` (10-digit Borough-Block-Lot composite, e.g. 1010110001 for the Empire State Building) for an exact lookup, OR pass `address` (partial-match) optionally constrained by `borough` (name or 2-letter code MN/BX/BK/QN/SI). The BBL returned here is the universal join key for all other property.nyc-* endpoints — fetch parcels first, then chain into deed-history, permits, or violations. operationId: property_nyc-parcel-lookup deprecated: false security: - x402Payment: [] responses: '200': description: 'Normalized envelope: items = NYC parcels.' 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: bbl: type: string description: 10-digit Borough-Block-Lot composite; empty string when borough could not be resolved. borough: type: string description: Borough name (Manhattan/Bronx/Brooklyn/Queens/Staten Island). block: type: number lot: type: number address: type: string nullable: true zipCode: type: string nullable: true zoningDistrict: type: string nullable: true landUse: type: string nullable: true buildingClass: type: string nullable: true ownerName: type: string nullable: true lotAreaSqFt: type: number nullable: true buildingAreaSqFt: type: number nullable: true residentialUnits: type: number nullable: true totalUnits: type: number nullable: true yearBuilt: type: number nullable: true yearAltered: type: number nullable: true numFloors: type: number nullable: true numBuildings: type: number nullable: true assessedLandUSD: type: number nullable: true assessedTotalUSD: type: number nullable: true lat: type: number nullable: true lon: type: number nullable: true communityDistrict: type: string nullable: true schoolDistrict: type: string nullable: true councilDistrict: type: string nullable: true policePrecinct: type: string nullable: true historicDistrict: type: string nullable: true required: - bbl - borough - block - lot - address - zipCode - zoningDistrict - landUse - buildingClass - ownerName - lotAreaSqFt - buildingAreaSqFt - residentialUnits - totalUnits - yearBuilt - yearAltered - numFloors - numBuildings - assessedLandUSD - assessedTotalUSD - lat - lon - communityDistrict - schoolDistrict - councilDistrict - policePrecinct - historicDistrict 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: property.nyc-parcel-lookup x-2s-version: null x-2s-price: usd: 0.003 x-2s-accepts: - x402 x-2s-response-shape: normalized x-payment-info: price: mode: fixed currency: USD amount: '0.003000' protocols: - x402: {} parameters: - name: bbl in: query required: false description: Bbl. schema: type: string pattern: ^[1-5][- 0-9]{9,19}$ - name: address in: query required: false description: Street address or full address string. schema: type: string minLength: 3 maxLength: 120 - name: borough in: query required: false description: Borough. schema: type: string pattern: ^([A-Za-z ]{2,15})$ - $ref: '#/components/parameters/TrialMode' /api/property/nyc-permits: get: tags: - property summary: NYC Department of Buildings permit issuance - every description: NYC Department of Buildings permit issuance — every construction, alteration, or demolition permit ever issued. Search by `bbl` (10-digit) or `address` (street_name substring). Filter by jobType (A1=Major Alteration, A2=Minor Alteration, A3=Minor Cosmetic, NB=New Building, DM=Demolition, etc.) or permitStatus (ISSUED, IN PROCESS, RE-ISSUED, REVOKED, etc.). Each row carries job + permit numbers, work type, building type, residential flag, filing/issuance/expiration dates, estimated fee. Use for construction-history agents, code-enforcement research, and zoning compliance checks. operationId: property_nyc-permits deprecated: false security: - x402Payment: [] responses: '200': description: 'Normalized envelope: items = nyc dob permit records.' 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: jobNumber: type: string jobDocNumber: type: string nullable: true jobType: type: string nullable: true description: e.g. A1, A2, NB, DM. permitType: type: string nullable: true permitSubtype: type: string nullable: true permitStatus: type: string nullable: true description: e.g. ISSUED, IN PROCESS. filingStatus: type: string nullable: true workType: type: string nullable: true selfCert: type: string nullable: true borough: type: string nullable: true block: type: string nullable: true lot: type: string nullable: true bin: type: string nullable: true houseNumber: type: string nullable: true streetName: type: string nullable: true zipCode: type: string nullable: true buildingType: type: string nullable: true residential: type: string nullable: true filingDate: type: string nullable: true issuanceDate: type: string nullable: true expirationDate: type: string nullable: true estFee: type: number nullable: true description: Estimated fee in USD. required: - jobNumber - jobDocNumber - jobType - permitType - permitSubtype - permitStatus - filingStatus - workType - selfCert - borough - block - lot - bin - houseNumber - streetName - zipCode - buildingType - residential - filingDate - issuanceDate - expirationDate - estFee 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: property.nyc-permits x-2s-version: null x-2s-price: usd: 0.003 x-2s-accepts: - x402 x-2s-response-shape: normalized x-payment-info: price: mode: fixed currency: USD amount: '0.003000' protocols: - x402: {} parameters: - name: bbl in: query required: false description: Bbl. schema: type: string pattern: ^[1-5][- 0-9]{9,19}$ - name: address in: query required: false description: Street address or full address string. schema: type: string minLength: 3 maxLength: 120 - name: jobType in: query required: false description: Job type. schema: type: string pattern: ^[A-Za-z0-9]{1,5}$ - name: permitStatus in: query required: false description: Permit status. schema: type: string pattern: ^[A-Za-z _-]{2,30}$ - name: limit in: query required: false description: Maximum number of results to return. schema: type: integer minimum: 1 maximum: 200 default: 25 - name: offset in: query required: false description: Number of results to skip before returning (pagination offset). schema: type: integer minimum: 0 default: 0 - $ref: '#/components/parameters/TrialMode' /api/property/nyc-violations: get: tags: - property summary: NYC Housing Preservation & Development (HPD) violations description: NYC Housing Preservation & Development (HPD) violations — every notice of violation issued at a multi-family building. Search by `bbl` (10-digit) or `address` (street_name substring). Filter by `classCode` (A=least severe, B=hazardous, C=immediately hazardous) and `currentStatusOnly=true` to limit to open violations. Each row carries violation id, building id, full address + apartment + story, inspection + approved + certify-by + correct-by dates, current status + status date, and the narrative NOV description. Use for landlord-history, code-enforcement, and tenant-rights agents. operationId: property_nyc-violations deprecated: false security: - x402Payment: [] responses: '200': description: 'Normalized envelope: items = nyc hpd violation records.' 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: violationId: type: string buildingId: type: string nullable: true borough: type: string nullable: true block: type: string nullable: true lot: type: string nullable: true houseNumber: type: string nullable: true streetName: type: string nullable: true apartment: type: string nullable: true story: type: string nullable: true zipCode: type: string nullable: true classCode: type: string nullable: true description: A/B/C severity class. inspectionDate: type: string nullable: true approvedDate: type: string nullable: true originalCertifyByDate: type: string nullable: true originalCorrectByDate: type: string nullable: true newCertifyByDate: type: string nullable: true newCorrectByDate: type: string nullable: true currentStatusId: type: number nullable: true currentStatus: type: string nullable: true currentStatusDate: type: string nullable: true novDescription: type: string nullable: true description: Narrative notice-of-violation text. required: - violationId - buildingId - borough - block - lot - houseNumber - streetName - apartment - story - zipCode - classCode - inspectionDate - approvedDate - originalCertifyByDate - originalCorrectByDate - newCertifyByDate - newCorrectByDate - currentStatusId - currentStatus - currentStatusDate - novDescription 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: property.nyc-violations x-2s-version: null x-2s-price: usd: 0.003 x-2s-accepts: - x402 x-2s-response-shape: normalized x-payment-info: price: mode: fixed currency: USD amount: '0.003000' protocols: - x402: {} parameters: - name: bbl in: query required: false description: Bbl. schema: type: string pattern: ^[1-5][- 0-9]{9,19}$ - name: address in: query required: false description: Street address or full address string. schema: type: string minLength: 3 maxLength: 120 - name: classCode in: query required: false description: Class code. schema: type: string enum: - A - B - C - name: currentStatusOnly in: query required: false description: Current status only. schema: type: boolean - name: limit in: query required: false description: Maximum number of results to return. schema: type: integer minimum: 1 maximum: 200 default: 25 - name: offset in: query required: false description: Number of results to skip before returning (pagination offset). schema: type: integer minimum: 0 default: 0 - $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.'