{"openapi":"3.1.0","info":{"title":"DripStack API","version":"0.1.0","description":"Paid API for listing publications and purchasing full Substack post content.","x-guidance":"How to use this API as an agent:\n1) Discovery: Prefer GET /openapi.json (OpenAPI 3.1) for paths, JSON schemas, and x-payment-info. If OpenAPI is unavailable, use GET /.well-known/x402 (version 1) for the paid resource list in \"METHOD /path\" form.\n2) Public data (no payment): GET /api/v1/publications lists known publications. GET /api/v1/publications/{publicationSlug} returns metadata and post titles. GET /api/publications/posts resolves a publication by publicationId or publicationTitle (substring must match exactly one publication) and returns paginated posts. POST /api/v1/publications/{publicationSlug} imports/refreshes a publication; body may include { forceRefresh?: boolean }.\n3) Paid content: GET /api/v1/publications/{publicationSlug}/{postSlug} returns full post JSON including contentHtml after payment. Unpaid: HTTP 402 with dual challenge (MPP `WWW-Authenticate: Payment …` and x402 v2 `PAYMENT-REQUIRED`). Retry with Authorization: Payment … (MPP) or PAYMENT-SIGNATURE (x402 v2). Runtime 402 amounts are authoritative (per-post USD from the catalog when present, else at least $0.05). OpenAPI may show a dynamic USD range for budgeting only.\n4) Query ?importer=1 on the paid post route skips payment and redirects into the web importer — not for API agents.\n\nAlways trust the live 402 challenge over static OpenAPI pricing metadata."},"x-discovery":{"ownershipProofs":["did:pkh:eip155:8453:0xBF22b6DdB5A08c823856A779f1004eEa60C5aB92"]},"paths":{"/api/v1/publications":{"get":{"operationId":"listPublications","summary":"List publications.","tags":["Publications"],"x-payment-info":{"authMode":"none","price":"0.00","protocols":[{"x402":{}},{"mpp":{"method":"","intent":"","currency":""}}]},"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"description":"Optional. This GET has no request body; send an empty JSON object or omit the body.","properties":{}}}}},"responses":{"200":{"description":"List of publications.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPublicationsResponse"}}}}}}},"/api/v1/publications/{publicationSlug}":{"get":{"operationId":"getPublication","summary":"Get one publication.","tags":["Publications"],"parameters":[{"name":"publicationSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Publication slug, which is the normalized host."}],"x-payment-info":{"authMode":"none","price":"0.00","protocols":[{"x402":{}},{"mpp":{"method":"","intent":"","currency":""}}]},"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"description":"Optional. This GET has no request body; send an empty JSON object or omit the body.","properties":{}}}}},"responses":{"200":{"description":"Publication details and post titles.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicationDetail"}}}},"404":{"description":"Publication not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorMessage"}}}}}},"post":{"operationId":"importPublication","summary":"Import one publication.","tags":["Publications"],"parameters":[{"name":"publicationSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Publication slug, which is the normalized host."}],"x-payment-info":{"authMode":"none","price":"0.00","protocols":[{"x402":{}},{"mpp":{"method":"","intent":"","currency":""}}]},"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"forceRefresh":{"type":"boolean","description":"When true, re-fetches publication feed even if records exist."}}}}}},"responses":{"200":{"description":"Publication imported successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportPublicationResponse"}}}},"404":{"description":"Publication not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorMessage"}}}}}}},"/api/v1/publications/{publicationSlug}/{postSlug}":{"get":{"operationId":"getPublicationPostBySlug","summary":"Get full post content (paid).","description":"Resolves the post, then returns HTTP 402 until the client pays via MPP and/or x402 on the same response (WWW-Authenticate + PAYMENT-REQUIRED). The challenge amount is the stored per-post price in USD, or at least $0.05 when the post has no source price (see OpenAPI x-payment-info dynamic range; runtime 402 is authoritative).","tags":["Posts"],"parameters":[{"name":"publicationSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Publication slug, which is the normalized host."},{"name":"postSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Post slug from the publication feed."},{"name":"Authorization","in":"header","required":false,"schema":{"type":"string"},"description":"MPP (Payment HTTP Authentication Scheme): after HTTP 402, retry with `Authorization: Payment <credential>`."},{"name":"PAYMENT-SIGNATURE","in":"header","required":false,"schema":{"type":"string"},"description":"x402 v2: after HTTP 402, retry with the encoded payment payload from the `PAYMENT-REQUIRED` challenge (same header name as in `@x402/core` HTTP transport)."}],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0.05","max":"10.00"},"protocols":[{"x402":{}},{"mpp":{"method":"","intent":"","currency":""}}]},"responses":{"200":{"description":"Full post body after successful payment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FullPublicationPost"}}}},"402":{"description":"Payment Required","headers":{"WWW-Authenticate":{"description":"MPP `Payment` HTTP Authentication Scheme challenge (realm must match origin).","schema":{"type":"string"}},"PAYMENT-REQUIRED":{"description":"x402 v2 encoded payment requirements (see x402 seller docs).","schema":{"type":"string"}}},"content":{"application/problem+json":{"schema":{"type":"object","required":["type","title","status","detail"],"properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","enum":[402]},"detail":{"type":"string"},"challengeId":{"type":"string"}}}}}},"404":{"description":"Publication or post not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorMessage"}}}}}}},"/api/publications/posts":{"get":{"operationId":"listPublicationPosts","summary":"List posts for a publication.","tags":["Posts"],"x-payment-info":{"authMode":"none","price":"0.00","protocols":[{"x402":{}},{"mpp":{"method":"","intent":"","currency":""}}]},"parameters":[{"name":"publicationId","in":"query","required":false,"schema":{"type":"string"},"description":"Publication id (exact). Use this or publicationTitle."},{"name":"publicationTitle","in":"query","required":false,"schema":{"type":"string"},"description":"Case-insensitive substring; must match exactly one publication."},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"description":"Optional. This GET has no request body; send an empty JSON object or omit the body.","properties":{}}}}},"responses":{"200":{"description":"Paginated posts for the resolved publication.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPublicationPostsResponse"}}}},"400":{"description":"Missing or ambiguous publication selector.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorMessage"}}}},"404":{"description":"Publication not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorMessage"}}}}}}}},"components":{"securitySchemes":{"siwx":{"type":"http","scheme":"bearer","bearerFormat":"SIWX","description":"SIWX wallet identity for identity-gated operations. No operation in this spec requires SIWX yet; paid routes use x402 / MPP only."}},"schemas":{"ErrorMessage":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"string"}}},"PublicationListItem":{"type":"object","additionalProperties":false,"required":["slug","siteUrl"],"properties":{"slug":{"type":"string"},"title":{"type":["string","null"]},"description":{"type":["string","null"]},"siteUrl":{"type":"string"},"lastSyncedAt":{"type":["string","null"]}}},"ListPublicationsResponse":{"type":"object","additionalProperties":false,"required":["publications"],"properties":{"publications":{"type":"array","items":{"$ref":"#/components/schemas/PublicationListItem"}}}},"PostSummary":{"type":"object","additionalProperties":false,"required":["slug","title"],"properties":{"slug":{"type":"string"},"title":{"type":"string"},"subtitle":{"type":["string","null"]}}},"PublicationCore":{"type":"object","additionalProperties":false,"required":["slug","title","description","siteUrl","imageUrl","language","authorName","authorEmail","copyright","lastSyncedAt"],"properties":{"slug":{"type":"string"},"title":{"type":["string","null"]},"description":{"type":["string","null"]},"siteUrl":{"type":"string"},"imageUrl":{"type":["string","null"]},"language":{"type":["string","null"]},"authorName":{"type":["string","null"]},"authorEmail":{"type":["string","null"]},"copyright":{"type":["string","null"]},"lastSyncedAt":{"type":["string","null"]}}},"PublicationDetail":{"allOf":[{"$ref":"#/components/schemas/PublicationCore"},{"type":"object","additionalProperties":false,"required":["posts"],"properties":{"posts":{"type":"array","items":{"$ref":"#/components/schemas/PostSummary"}}}}]},"ImportPublicationResponse":{"allOf":[{"$ref":"#/components/schemas/PublicationCore"},{"type":"object","additionalProperties":false,"required":["postCount"],"properties":{"postCount":{"type":"integer","minimum":0}}}]},"PublicationPostListItem":{"type":"object","additionalProperties":false,"required":["id","title","createdAt"],"properties":{"id":{"type":"string"},"title":{"type":"string"},"subtitle":{"type":["string","null"]},"description":{"type":["string","null"]},"author":{"type":["string","null"]},"createdAt":{"type":"string"}}},"ListPublicationPostsResponse":{"type":"object","additionalProperties":false,"required":["publicationId","items","page","limit","total","totalPages","hasNextPage","hasPreviousPage"],"properties":{"publicationId":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/PublicationPostListItem"}},"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0},"totalPages":{"type":"integer","minimum":1},"hasNextPage":{"type":"boolean"},"hasPreviousPage":{"type":"boolean"}}},"FullPublicationPost":{"type":"object","additionalProperties":false,"required":["id","publicationId","publicationSlug","guid","slug","title","subtitle","description","url","author","imageUrl","publishedAt","contentHtml","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"publicationId":{"type":"string"},"publicationSlug":{"type":"string"},"guid":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"subtitle":{"type":["string","null"]},"description":{"type":["string","null"]},"url":{"type":"string"},"author":{"type":["string","null"]},"imageUrl":{"type":["string","null"]},"publishedAt":{"type":["string","null"]},"contentHtml":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}}}}