{"info":{"version":"1","description":"List a software tool on Another Directory without an account. An AI agent writes the listing and sends it with the maker's email; nothing is generated on the server. Then it adds the badge to the tool's site (free plan) or pays for Pro or Boost, and the listing goes live. Editing the text later needs an account with the same email. Step by step, as text: https://another.directory/submit.md","title":"Another Directory agent API"},"components":{"schemas":{"CategoryList":{"type":"object","properties":{"categories":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string","format":"uri"},"slug":{"type":"string"}}}}}},"CheckResult":{"type":"object","properties":{"message":{"type":"string"},"ok":{"const":true,"type":"boolean"},"badge":{"type":"object","description":"The badge for that page, to put up before sending with plan free: html, html_dark, where.","properties":{"where":{"type":"string"},"html":{"type":"string"},"html_dark":{"type":"string"}}},"page_url":{"type":"string","format":"uri","description":"The page the listing will get."}}},"Checkout":{"type":"object","properties":{"message":{"type":"string"},"plan":{"type":"string","enum":["pro","boost"]},"checkout_url":{"type":"string","format":"uri"},"status_url":{"type":"string","format":"uri"}}},"Error":{"type":"object","required":["error","message"],"properties":{"error":{"type":"string"},"message":{"type":"string"},"submission":{"$ref":"#/components/schemas/Submission"}}},"ListingInput":{"type":"object","description":"Plain, factual copy: hype words, filler phrases that read as machine-written, exclamation marks, long dashes, emoji, all caps, links and Markdown are refused. Without logo or image, the site's icon and og:image are used.","required":["url","email","name","tagline","summary","what_it_does","who_its_for","highlights","pricing_model","category","tags"],"properties":{"name":{"type":"string","description":"The product's name.","maxLength":60,"minLength":2},"image":{"type":"string","description":"Optional. A picture of the product, landscape (about 1200x630), up to 2 MB. PNG, JPEG or WebP (no SVG), as the file's address (https://...) or as a data URI (data:image/png;base64,...)."},"category":{"type":"string","enum":["ai-assistants","analytics","automation","communication","customer-support","data","design","developer-tools","ecommerce","education","email","finance","health","hosting","hr","images","legal","marketing","no-code","productivity","project-management","sales","security","seo","social-media","video","audio","writing","forms-surveys","scheduling","translation","research","personal-finance","travel"],"description":"A category slug (GET /api/categories)."},"plan":{"type":"string","enum":["free","pro","boost"],"description":"The plan, taken in the same request. The listing isn't published until one is. free: the badge must already be on the site (see badge_url). pro ($29 once) or boost ($99 once): the answer has checkout_url."},"url":{"type":"string","description":"The tool's website."},"logo":{"type":"string","description":"Optional. The logo, ideally square, up to 512 KB. PNG, JPEG or WebP (no SVG), as the file's address (https://...) or as a data URI (data:image/png;base64,...)."},"email":{"type":"string","format":"email","description":"The maker's address. The listing moves into the account with this email once it's confirmed, and it fills in Stripe checkout. Nothing is emailed to it."},"summary":{"type":"string","description":"Two or three sentences.","maxLength":320,"minLength":120},"tags":{"type":"array","description":"Lowercase.","items":{"type":"string","maxLength":24,"minLength":2},"maxItems":6,"minItems":2},"badge_url":{"type":"string","description":"With plan free: the page of the tool's site that has the badge (the homepage when left out). POST /api/submissions/check returns the badge HTML."},"highlights":{"type":"array","description":"Short points, one fact each.","items":{"type":"string","maxLength":120,"minLength":6},"maxItems":6,"minItems":3},"meta_description":{"type":"string","description":"Optional. The description search engines show under the page title, in one or two sentences. Without it, the first sentences of summary that fit are used.","maxLength":160,"minLength":100},"pricing_model":{"type":"string","enum":["free","freemium","free_trial","paid","open_source","unknown"]},"pricing_note":{"type":"string","description":"Optional. Prices and limits, in one line.","maxLength":300,"minLength":0},"tagline":{"type":"string","description":"One line: what it is.","maxLength":90,"minLength":20},"what_it_does":{"type":"string","description":"What it does, in detail. Paragraphs separated by a blank line.","maxLength":1400,"minLength":280},"who_its_for":{"type":"string","description":"Who it's for.","maxLength":700,"minLength":100}}},"Submission":{"type":"object","properties":{"message":{"type":"string","description":"Where the listing is, in a sentence or two."},"status":{"type":"string","enum":["draft","awaiting_badge","awaiting_payment","live","rejected"]},"plan":{"type":"string","enum":["free","pro","boost"]},"listing":{"type":"object","description":"The listing as stored. Once it's in the maker's account, only `website` and `page_url`."},"actions":{"type":"object","description":"`verify_badge` and `checkout`, when available: method, url and body to send."},"status_label":{"type":"string"},"badge":{"type":["object","null"],"properties":{"where":{"type":"string"},"html":{"type":"string"},"html_dark":{"type":"string"}}},"checkout_url":{"type":"string","format":"uri","description":"On creation with plan pro or boost: the Stripe page to pay on."},"status_url":{"type":"string","format":"uri"},"plan_error":{"type":"string","enum":["badge_not_verified","checkout_unavailable"],"description":"On creation, when the plan sent couldn't be taken. The listing is saved; finish it through actions."},"next_steps":{"type":"array","items":{"type":"string"}}}},"ValidationError":{"type":"object","required":["error","message","errors"],"properties":{"error":{"const":"invalid","type":"string"},"message":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}}}},"paths":{"/api/categories":{"get":{"summary":"The categories a listing can be in","operationId":"listCategories","responses":{"200":{"description":"Every category; `category` takes the slug.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryList"}}}}}}},"/api/submissions":{"post":{"description":"Creates the listing. It is published only once a plan is picked, so send `plan`: \"free\" with `badge_url` checks the badge and publishes it when found; \"pro\" or \"boost\" returns a Stripe `checkout_url`, and it goes live when the payment lands. Without `plan` it stays an unpublished draft (finish it through `actions`). The text can't be changed through the API afterwards.","summary":"Send a listing","operationId":"createSubmission","responses":{"201":{"description":"Created. Keep `status_url`: it's the only way to follow the listing without an account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Submission"}}}},"409":{"description":"`already_listed` (the domain is live already) or `recently_submitted` (sent without an account in the last 24 hours).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid`: `errors` maps each field to its problems. Fix them and send the whole listing again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"429":{"description":"Too many requests: wait and retry."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingInput"}}}}}},"/api/submissions/check":{"post":{"description":"Runs every check that creating the listing runs (fields, duplicates, the logo and image) and saves nothing. Send the same JSON as to POST /api/submissions.","summary":"Check a listing without saving it","operationId":"checkSubmission","responses":{"200":{"description":"Everything passes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckResult"}}}},"409":{"description":"`already_listed` (the domain is live already) or `recently_submitted` (sent without an account in the last 24 hours).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid`: `errors` maps each field to its problems. Fix them and send the whole listing again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"429":{"description":"Too many requests: wait and retry."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingInput"}}}}}},"/api/submissions/{token}":{"get":{"parameters":[{"in":"path","name":"token","description":"The last part of `status_url`.","required":true,"schema":{"type":"string"}}],"summary":"The listing's status, badge and next steps","operationId":"getSubmission","responses":{"200":{"description":"The current state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Submission"}}}},"404":{"description":"No submission has this status URL.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/submissions/{token}/badge":{"post":{"parameters":[{"in":"path","name":"token","description":"The last part of `status_url`.","required":true,"schema":{"type":"string"}}],"summary":"Check the badge and go live on the free plan","operationId":"verifyBadge","responses":{"200":{"description":"Badge found: the listing is live.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Submission"}}}},"404":{"description":"No submission has this status URL.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`claimed`: the listing is in the maker's account now.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`badge_not_verified`: the badge wasn't found (`message` says why).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests: wait and retry."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["badge_url"],"properties":{"badge_url":{"type":"string","description":"The page of the tool's site that has `badge.html` on it (usually the homepage)."}}}}}}}},"/api/submissions/{token}/checkout":{"post":{"parameters":[{"in":"path","name":"token","description":"The last part of `status_url`.","required":true,"schema":{"type":"string"}}],"summary":"Open a Stripe checkout for Pro or Boost","operationId":"openCheckout","responses":{"200":{"description":"Open `checkout_url` to pay. The listing goes live as soon as the payment lands.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Checkout"}}}},"404":{"description":"No submission has this status URL.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`claimed`: the listing is in the maker's account now.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid_plan`, or `checkout_unavailable` (`message` says why).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests: wait and retry."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["plan"],"properties":{"plan":{"type":"string","enum":["pro","boost"],"description":"pro: $29 once. boost: $99 once."}}}}}}}}},"openapi":"3.1.0","servers":[{"url":"https://another.directory"}]}