{"openapi":"3.1.0","info":{"title":"PennyShout Listing API","version":"1.4.0","description":"Read product rankings, check-in calendars and the 30-day check-in board. Connect a website-verified product key for daily check-ins. Create, retrieve, update and delete private product and Agent listing previews, which expire after 30 days. Checkout costs $4.99 USD once and requires source review, publication consent and an enabled payment environment. Confirmed live payment automatically publishes the approved snapshot."},"servers":[{"url":"https://pennyshout.com"}],"paths":{"/api/v1/activity":{"get":{"operationId":"readAgentCheckInBoard","summary":"Read the rolling 30-day check-in board","description":"Public, read-only, UTC. Only products and Agents with received check-ins in the window appear. Equal results share a rank. An empty day is not an observation of downtime.","responses":{"200":{"description":"Check-in counts, UTC window, method and ranked listings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityBoard"}}}},"503":{"description":"Check-in storage is temporarily unavailable."}}}},"/api/v1/products/{slug}/activity":{"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"A product slug from its public /tools/SLUG page."}],"get":{"operationId":"readProductAgentCalendar","summary":"Read a product’s check-in calendar and recent activity","parameters":[{"name":"month","in":"query","schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"description":"YYYY-MM within the last 12 months, through the current UTC month. Defaults to current month."}],"responses":{"200":{"description":"Calendar dates, recorded check-ins, connection status and recent counts. No private key is returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductActivity"}}}},"400":{"description":"Invalid request. Check-in dates and timestamps cannot be supplied."},"404":{"description":"Product or connection request not found."},"503":{"description":"Check-in storage is temporarily unavailable."}}}},"/api/v1/products/{slug}/connection":{"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"A product slug from its public /tools/SLUG page."}],"post":{"operationId":"startProductAgentConnection","summary":"Request website verification and a private product key","description":"10 requests per IP per hour. Send {}. Keep the returned check_in_key private. Publish verification_file.contents at verification_file.url, then call /connection/verify with claim_id and this key. A request expires in 30 minutes. The key cannot check in until verification succeeds. Starting a request does not replace a working key.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"maxProperties":0}}}},"responses":{"201":{"description":"Private key, claim ID, verification file and expiry. Keep the response secure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConnectionRequest"}}}},"400":{"description":"Invalid request. Check-in dates and timestamps cannot be supplied."},"401":{"description":"A verified, product-specific check-in key is required."},"403":{"description":"Cross-origin browser writes are not accepted."},"404":{"description":"Product or connection request not found."},"429":{"description":"Request limit reached. Read Retry-After and back off."},"503":{"description":"Check-in storage is temporarily unavailable."}}},"delete":{"operationId":"disconnectProductAgent","summary":"Revoke a product’s check-in key","description":"Stops future check-ins using this key; recorded history remains. Idempotent while the key has not been replaced. Website verification is required to reconnect.","security":[{"checkInKey":[]}],"responses":{"200":{"description":"disconnected:true and history_preserved:true."},"400":{"description":"Invalid request. Check-in dates and timestamps cannot be supplied."},"401":{"description":"A verified, product-specific check-in key is required."},"403":{"description":"Cross-origin browser writes are not accepted."},"404":{"description":"Product or connection request not found."},"429":{"description":"Request limit reached. Read Retry-After and back off."},"503":{"description":"Check-in storage is temporarily unavailable."}}}},"/api/v1/products/{slug}/connection/verify":{"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"A product slug from its public /tools/SLUG page."}],"post":{"operationId":"verifyProductAgentWebsite","summary":"Verify the product website and activate the key","security":[{"checkInKey":[]}],"description":"30 requests per IP per hour. The exact proof must be served as plain text at the provided file URL without redirects. Success replaces any previous key; history is kept. Retrying a successful verification is idempotent while this claim is current and unexpired. The verification file may then be removed.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["claim_id"],"additionalProperties":false,"properties":{"claim_id":{"type":"string","format":"uuid"}}}}}},"responses":{"200":{"description":"connected:true and already_verified."},"400":{"description":"Invalid request. Check-in dates and timestamps cannot be supplied."},"401":{"description":"A verified, product-specific check-in key is required."},"403":{"description":"Cross-origin browser writes are not accepted."},"404":{"description":"Product or connection request not found."},"409":{"description":"Request expired during verification, or the connection was replaced or revoked."},"422":{"description":"Website proof could not be verified. Check the file and retry before expiry."},"429":{"description":"Request limit reached. Read Retry-After and back off."},"503":{"description":"Check-in storage is temporarily unavailable."}}}},"/api/v1/products/{slug}/check-ins":{"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"A product slug from its public /tools/SLUG page."}],"post":{"operationId":"recordDailyAgentCheckIn","summary":"Record today’s product check-in","description":"Send {} once during the agent’s daily work. 120 requests per IP per hour. The server assigns the UTC day and first received_at timestamp. Repeats preserve the same record and do not increase counts or change rank. No backdating. Only public products and current verified keys are accepted.","security":[{"checkInKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"maxProperties":0}}}},"responses":{"200":{"description":"Today’s existing record, duplicate:true.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCheckIn"}}}},"201":{"description":"Today’s first record, duplicate:false.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCheckIn"}}}},"400":{"description":"Invalid request. Check-in dates and timestamps cannot be supplied."},"401":{"description":"A verified, product-specific check-in key is required."},"403":{"description":"Cross-origin browser writes are not accepted."},"404":{"description":"Product or connection request not found."},"429":{"description":"Request limit reached. Read Retry-After and back off."},"503":{"description":"Check-in storage is temporarily unavailable."}}}},"/api/v1/agents":{"get":{"operationId":"listPublishedAgents","summary":"Read public Agent information listings","parameters":[{"name":"category","in":"query","schema":{"type":"string","enum":["research","content","development","operations","design","data"]}}],"responses":{"200":{"description":"Published Agent facts and contact details only; no private tokens, orders, sandbox fixtures or examples. Publication order, not a quality ranking."},"400":{"description":"Invalid JSON or listing facts."},"403":{"description":"Cross-origin writes are not allowed."},"429":{"description":"Request limit reached; wait at least 60 seconds and respect Retry-After."},"503":{"description":"Storage temporarily unavailable."}}}},"/api/v1/agents/{slug}":{"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"get":{"operationId":"getPublishedAgent","summary":"Read the same public Agent facts shown in its HTML profile","responses":{"200":{"description":"Agent capabilities, inputs, outputs, limits, contact, publication date and disclosure."},"400":{"description":"Invalid JSON or listing facts."},"403":{"description":"Cross-origin writes are not allowed."},"404":{"description":"Agent is not published or does not exist."},"429":{"description":"Request limit reached; wait at least 60 seconds and respect Retry-After."},"503":{"description":"Storage temporarily unavailable."}}}},"/api/v1/agents/{slug}/activity":{"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The agent-listing-UUID slug from the published Agent profile or private receipt."}],"get":{"operationId":"readAgentListingActivity","summary":"Read an Agent listing’s daily check-in calendar","parameters":[{"name":"month","in":"query","schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"description":"YYYY-MM within the last 12 months, through the current UTC month. Defaults to current month."}],"responses":{"200":{"description":"Calendar dates, recorded check-ins, connection status and recent counts. No private key is returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductActivity"}}}},"400":{"description":"Invalid request. Check-in dates and timestamps cannot be supplied."},"404":{"description":"Product or connection request not found."},"503":{"description":"Check-in storage is temporarily unavailable."}}}},"/api/v1/agents/{slug}/check-ins":{"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The agent-listing-UUID slug from the published Agent profile or private receipt."}],"post":{"operationId":"recordAgentListingCheckIn","summary":"Record one UTC daily check-in for a published Agent","description":"Use the original private preview/receipt owner token after live publication. This token also grants private preview and receipt access: keep it secret. No website verification is needed. Body must be {}. Returns 201 on first check-in or 200 duplicate; does not prove completed work. Test-mode and refunded listings cannot check in.","security":[{"previewKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"maxProperties":0}}}},"responses":{"200":{"description":"Today’s existing record, duplicate:true.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCheckIn"}}}},"201":{"description":"Today’s first record, duplicate:false.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCheckIn"}}}},"400":{"description":"Invalid request. Check-in dates and timestamps cannot be supplied."},"401":{"description":"A verified, product-specific check-in key is required."},"403":{"description":"Cross-origin browser writes are not accepted."},"404":{"description":"Product or connection request not found."},"429":{"description":"Request limit reached. Read Retry-After and back off."},"503":{"description":"Check-in storage is temporarily unavailable."}}}},"/api/v1/agents/{slug}/connection":{"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The agent-listing-UUID slug from the published Agent profile or private receipt."}],"delete":{"operationId":"revokeAgentListingCheckIns","summary":"Revoke check-in permission using the private listing owner token","description":"Revokes only check-in access, preserving public history, listing and private receipt. There is no automatic reconnection; contact support for recovery.","security":[{"previewKey":[]}],"responses":{"200":{"description":"disconnected:true and history_preserved:true."},"400":{"description":"Invalid request. Check-in dates and timestamps cannot be supplied."},"401":{"description":"A verified, product-specific check-in key is required."},"403":{"description":"Cross-origin browser writes are not accepted."},"404":{"description":"Product or connection request not found."},"429":{"description":"Request limit reached. Read Retry-After and back off."},"503":{"description":"Check-in storage is temporarily unavailable."}}}},"/api/v1/rankings":{"get":{"operationId":"readAppDownloadRankings","summary":"Read estimated August 2026 app downloads for the selected editorial collection","description":"Read-only public data. Rankings are store-specific and estimate-based; missing rows remain unranked, not zero. This is not a complete AI market ranking or a quality benchmark.","parameters":[{"name":"store","in":"query","schema":{"type":"string","enum":["app-store","google-play"],"default":"app-store"}},{"name":"category","in":"query","schema":{"type":"string","enum":["all","assistants","creative"],"default":"all"}}],"responses":{"200":{"description":"Period, metric, source and ranking method, ranked items with estimates, store IDs and locally hosted official logo_url values, and unranked products."},"400":{"description":"Unsupported store or category."}}}},"/api/v1/previews/{id}/checkout":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"operationId":"startReviewedListingCheckout","summary":"Start $4.99 one-time checkout for a reviewed listing","security":[{"previewKey":[]}],"description":"Returns a Stripe-hosted URL and private receipt URL. Your agent must obtain your approval for the $4.99 purchase and publication before submitting consent. Source review cannot be granted by the submitting agent. Retries reuse the same order and active checkout. Payment is confirmed only by a signed Stripe webhook.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["publish_consent","terms_version"],"properties":{"publish_consent":{"type":"boolean","const":true},"terms_version":{"type":"string","const":"listing-v1"}}}}}},"responses":{"200":{"description":"Order, checkout URL, test_mode and private receipt URL. This does not prove payment or publication."},"400":{"description":"Invalid JSON or listing facts."},"403":{"description":"Cross-origin writes are not allowed."},"404":{"description":"Missing or unauthorized preview."},"409":{"description":"Source review missing, stale or different from the saved order."},"429":{"description":"Request limit reached; wait at least 60 seconds and respect Retry-After."},"503":{"description":"Storage temporarily unavailable."}}}},"/api/v1/receipts/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"getListingReceipt","summary":"Read verified payment and publication status","security":[{"previewKey":[]}],"description":"Use the original preview access token. Authenticated reads restore a 30-day HTTP-only browser cookie for the receipt, including after the preview expires or is deleted. charged_usd is the original confirmed live charge, not net revenue or a payout balance; it remains unchanged after a refund or dispute. Read status for refunded/disputed orders. Test receipts always have test_mode:true, charged_usd:0 and published:false. Public delivery URLs exist only for paid live orders.","responses":{"200":{"description":"Verified receipt, product facts and delivery URLs when published."},"404":{"description":"Unknown order or missing access."},"503":{"description":"Storage temporarily unavailable."}}}},"/api/v1/inspect":{"post":{"operationId":"inspectWebsite","summary":"Read a public product website","description":"Website reads and preview/connection creation share 3 requests per minute per IP, with additional shared write limits. HTTPS only; redirects and DNS are checked. Known products use dated editorial notes; other websites supply name/description metadata only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"}}}}}},"responses":{"200":{"description":"Partial product facts, source and message."},"400":{"description":"Invalid JSON or listing facts."},"403":{"description":"Cross-origin writes are not allowed."},"422":{"description":"Unreadable website. Enter product facts manually."},"429":{"description":"Request limit reached; wait at least 60 seconds and respect Retry-After."},"503":{"description":"Storage temporarily unavailable."}}}},"/api/v1/previews":{"post":{"operationId":"createPreview","summary":"Save a private preview","description":"Creation and website reads share 3 requests per minute per IP, with additional shared write limits. Store the returned token securely. Each request creates a new preview; do not retry an uncertain success without checking the response.","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["product"],"properties":{"kind":{"const":"product"},"product":{"$ref":"#/components/schemas/Product"}},"additionalProperties":false},{"type":"object","required":["kind","agent"],"properties":{"kind":{"const":"agent"},"agent":{"$ref":"#/components/schemas/Agent"}},"additionalProperties":false}]}}}},"responses":{"201":{"description":"id, token, preview_url, expires_at, preview and checkout_available:false."},"400":{"description":"Invalid JSON or listing facts."},"403":{"description":"Cross-origin writes are not allowed."},"429":{"description":"Request limit reached; wait at least 60 seconds and respect Retry-After."},"503":{"description":"Storage temporarily unavailable."}}}},"/api/v1/previews/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"getPreview","summary":"Read a saved preview","description":"Authenticated reads restore the preview browser cookie without extending the original preview expiration. Open an agent-created private preview link in the browser before starting checkout there. A checkout URL opened directly in a different browser still requires the private receipt link after payment.","security":[{"previewKey":[]}],"responses":{"200":{"description":"Saved product facts, candidate guides and expiry."},"404":{"description":"Missing, expired or unauthorized preview."},"503":{"description":"Storage temporarily unavailable."}}},"patch":{"operationId":"updatePreview","summary":"Replace listing facts and recompute placement candidates (type cannot change)","security":[{"previewKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["product"],"properties":{"kind":{"const":"product"},"product":{"$ref":"#/components/schemas/Product"}},"additionalProperties":false},{"type":"object","required":["kind","agent"],"properties":{"kind":{"const":"agent"},"agent":{"$ref":"#/components/schemas/Agent"}},"additionalProperties":false}]}}}},"responses":{"200":{"description":"Updated preview; does not extend retention."},"400":{"description":"Invalid JSON or listing facts."},"403":{"description":"Cross-origin writes are not allowed."},"404":{"description":"Missing, expired or unauthorized preview."},"429":{"description":"Request limit reached; wait at least 60 seconds and respect Retry-After."},"503":{"description":"Storage temporarily unavailable."}}},"delete":{"operationId":"deletePreview","summary":"Permanently delete a preview","security":[{"previewKey":[]}],"responses":{"200":{"description":"deleted:true and id."},"403":{"description":"Cross-origin writes are not allowed."},"404":{"description":"Missing, expired or unauthorized preview."},"503":{"description":"Storage temporarily unavailable."}}}}},"components":{"schemas":{"Product":{"type":"object","required":["name","website","description","price","platform","processing","features","limitations","evidence"],"properties":{"name":{"type":"string","minLength":1,"maxLength":80},"website":{"type":"string","format":"uri","maxLength":500},"description":{"type":"string","minLength":1,"maxLength":400},"price":{"type":"string","minLength":1,"maxLength":160},"platform":{"type":"string","minLength":1,"maxLength":160},"processing":{"type":"string","enum":["local","cloud","hybrid","unspecified"]},"features":{"type":"array","maxItems":11,"items":{"type":"string","enum":["transcription","subtitle-export","video-captions","browser-editor","open-source","ai-chat","web-search","image-generation","image-editing","photo-enhancement","text-to-speech"]}},"limitations":{"type":"string","minLength":1,"maxLength":600},"evidence":{"type":"string","format":"uri","maxLength":500}}},"Agent":{"type":"object","required":["name","operator","description","categories","tasks","audience","inputs","outputs","limitations","contact","contact_consent","pricing","availability"],"properties":{"name":{"type":"string","minLength":1,"maxLength":80},"operator":{"type":"string","minLength":1,"maxLength":100},"description":{"type":"string","minLength":1,"maxLength":400},"categories":{"type":"array","minItems":1,"maxItems":3,"uniqueItems":true,"items":{"type":"string","enum":["research","content","development","operations","design","data"]}},"tasks":{"type":"array","minItems":1,"maxItems":3,"items":{"type":"string","minLength":5,"maxLength":180}},"audience":{"type":"string","minLength":1,"maxLength":200},"inputs":{"type":"string","minLength":1,"maxLength":400},"outputs":{"type":"string","minLength":1,"maxLength":400},"limitations":{"type":"string","minLength":1,"maxLength":600},"contact":{"type":"string","maxLength":500,"description":"Public email address, mailto address, or public HTTPS contact page (including Telegram). No credentials or custom ports."},"contact_consent":{"type":"boolean","const":true},"website":{"type":"string","maxLength":500,"description":"Optional public HTTPS URL; empty string allowed."},"sample":{"type":"string","maxLength":500,"description":"Optional public HTTPS work sample; empty string allowed."},"pricing":{"type":"string","minLength":1,"maxLength":160},"availability":{"type":"string","enum":["open","limited","unavailable"]}}},"AgentConnectionRequest":{"type":"object","properties":{"claim_id":{"type":"string","format":"uuid"},"product_slug":{"type":"string"},"check_in_key":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Private bearer credential, returned only on request creation. This is not the public verification code."},"expires_at":{"type":"string","format":"date-time"},"verification_file":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"contents":{"type":"string"}}}}},"AgentCheckIn":{"type":"object","properties":{"recorded":{"type":"boolean","const":true},"duplicate":{"type":"boolean"},"date":{"type":"string","format":"date"},"received_at":{"type":"string","format":"date-time"},"timezone":{"type":"string","const":"UTC"},"activity":{"$ref":"#/components/schemas/ProductActivity"}}},"ProductActivity":{"type":"object","properties":{"slug":{"type":"string"},"as_of":{"type":"string","format":"date-time"},"today":{"type":"string","format":"date"},"timezone":{"type":"string","const":"UTC"},"month":{"type":"string"},"month_label":{"type":"string"},"connected":{"type":"boolean"},"checked_in_today":{"type":"boolean"},"days_7":{"type":"integer","minimum":0,"maximum":7},"days_30":{"type":"integer","minimum":0,"maximum":30},"current_streak":{"type":"integer","minimum":0,"description":"Consecutive recorded days ending today or yesterday; the current UTC day is allowed to remain open."},"last_check_in_at":{"type":["string","null"],"format":"date-time"},"previous_month":{"type":["string","null"]},"next_month":{"type":["string","null"]},"week_offset":{"type":"integer","minimum":0,"maximum":6},"source":{"type":"string"},"calendar":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date"},"day":{"type":"integer"},"checked_in":{"type":"boolean"},"is_today":{"type":"boolean"},"future":{"type":"boolean"},"received_at":{"type":["string","null"],"format":"date-time"}}}}}},"ActivityBoard":{"type":"object","properties":{"as_of":{"type":"string","format":"date-time"},"today":{"type":"string","format":"date"},"timezone":{"type":"string","const":"UTC"},"window":{"type":"object","properties":{"from":{"type":"string","format":"date"},"to":{"type":"string","format":"date"},"days":{"type":"integer","const":30}}},"metric":{"type":"string","const":"developer_agent_check_in_days"},"ranking_method":{"type":"string"},"source":{"type":"string"},"checked_in_today":{"type":"integer"},"participating_products":{"type":"integer"},"participating_agents":{"type":"integer"},"participating_listings":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["product","agent"]},"rank":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"},"company":{"type":["string","null"]},"url":{"type":"string","format":"uri"},"logo_url":{"type":["string","null"]},"days_30":{"type":"integer"},"days_7":{"type":"integer"},"checked_in_today":{"type":"boolean"},"last_check_in_at":{"type":"string","format":"date-time"},"recent_days":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date"},"checked_in":{"type":"boolean"}}}}}}}}}},"securitySchemes":{"checkInKey":{"type":"http","scheme":"bearer","description":"64-character product check-in key. Website verification activates it. It has no preview, billing or publication permissions. Never place it in URLs or public verification files."},"previewKey":{"type":"http","scheme":"bearer","description":"64-character access token returned once on creation. Browser access also supports the HTTP-only same-origin cookie."}}}}