{"openapi":"3.1.0","info":{"title":"ListBulb REST API","version":"v1","description":"Read ListBulb’s live catalog anonymously. Use a personal API key to create private, owner-bound drafts. API calls never publish, pay, schedule a launch, verify a badge, or submit a product for review."},"servers":[{"url":"https://www.listbulb.com","description":"Production"}],"tags":[{"name":"Catalog","description":"Public, live ListBulb listings."},{"name":"Taxonomy","description":"Categories and tags used by live listings."},{"name":"Drafts","description":"Private owner-bound drafts created with personal API keys."}],"paths":{"/api/v1/tools":{"get":{"operationId":"listTools","tags":["Catalog"],"summary":"List or search live tools","security":[],"description":"Returns only live listings. Pass the previous response’s `pagination.nextCursor` as `cursor` to continue.","parameters":[{"name":"cursor","in":"query","description":"Cursor returned by the previous page.","schema":{"type":"string","maxLength":256}},{"name":"q","in":"query","description":"Free-text search.","schema":{"type":"string","minLength":2,"maxLength":100}},{"name":"category","in":"query","description":"Category slug or name.","schema":{"type":"string","minLength":1,"maxLength":80}},{"name":"tag","in":"query","description":"Tag slug or name.","schema":{"type":"string","minLength":1,"maxLength":80}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":25,"default":10}}],"responses":{"200":{"description":"Live catalog results.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolListResponse"}}}},"400":{"description":"One or more query parameters are invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"INVALID_QUERY","message":"One or more query parameters are invalid."}}}}}}},"post":{"operationId":"createToolDraft","tags":["Drafts"],"summary":"Create a private owner-bound draft","security":[{"bearerAuth":[]}],"description":"Requires a personal key from `/account/api-keys`. Replaying the same idempotency key with identical data returns the original draft; reusing it with changed data returns `409`. Limited to 10 new drafts per API key per 24 hours.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"A unique 16–256 character key per draft.","schema":{"type":"string","minLength":16,"maxLength":256}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductDraftInput"},"example":{"name":"Acme","headline":"A focused workspace","description":"A clear product description with enough detail for a founder to review, edit, and finish their private ListBulb product draft before it can enter the normal submission workflow.","websiteUrl":"https://acme.example","screenshotUrls":["https://acme.example/screenshot.png"],"category":"productivity","slug":"acme"}}}},"responses":{"201":{"description":"Private draft created, or the original result returned for an idempotent replay.","headers":{"Location":{"schema":{"type":"string","format":"uri"},"description":"Absolute private editor URL for the draft."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DraftResponse"}}}},"400":{"description":"Product details or the idempotency key are invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Product details or the idempotency key are invalid."}}}}},"401":{"description":"Send an active API key in Authorization: Bearer lb_…","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"API_KEY_REQUIRED","message":"Send an active API key in Authorization: Bearer lb_…"}}}}},"403":{"description":"The API key owner is unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"OWNER_UNAVAILABLE","message":"The API key owner is unavailable."}}}}},"409":{"description":"This idempotency key was already used with different product data.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"IDEMPOTENCY_CONFLICT","message":"This idempotency key was already used with different product data."}}}}},"422":{"description":"Screenshot and logo could not be resolved from supplied URLs or the website.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"MEDIA_REQUIRED","message":"Screenshot and logo could not be resolved from supplied URLs or the website."}}}}},"429":{"description":"Too many API drafts. Try again later.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until a creation attempt may be retried."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many API drafts. Try again later."}}}}},"503":{"description":"Draft creation is temporarily unavailable because rate-limit storage cannot be reached.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until a creation attempt may be retried."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"RATE_LIMIT_UNAVAILABLE","message":"Draft creation is temporarily unavailable because rate-limit storage cannot be reached."}}}}}}}},"/api/v1/tools/{slug}":{"get":{"operationId":"getTool","tags":["Catalog"],"summary":"Get one live tool","security":[],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":120,"pattern":"^[a-z0-9][a-z0-9-]*$"}}],"responses":{"200":{"description":"Live tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResponse"}}}},"400":{"description":"The slug is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"INVALID_SLUG","message":"The slug is invalid."}}}}},"404":{"description":"No live tool exists with this slug.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"TOOL_NOT_FOUND","message":"No live tool exists with this slug."}}}}}}}},"/api/v1/categories":{"get":{"operationId":"listCategories","tags":["Taxonomy"],"summary":"List live categories","security":[],"responses":{"200":{"description":"Categories containing live tools.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryListResponse"}}}}}}},"/api/v1/tags":{"get":{"operationId":"listTags","tags":["Taxonomy"],"summary":"List live tags","security":[],"responses":{"200":{"description":"Tags assigned to live tools.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagListResponse"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"lb_… API key","description":"Personal API key created at /account/api-keys. Keys are owner-bound and become permanently invalid when revoked."}},"schemas":{"ApiMeta":{"type":"object","required":["apiVersion"],"properties":{"apiVersion":{"type":"string","example":"v1"}}},"ErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Safe human-readable explanation."}}}}},"Tool":{"type":"object","required":["slug","name","websiteUrl","listbulbUrl","description","listingHeadline","logoUrl","imageUrl","category","tags","listedAt","featured","verification"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"websiteUrl":{"type":"string","format":"uri"},"listbulbUrl":{"type":"string","format":"uri"},"description":{"type":["string","null"]},"listingHeadline":{"type":["string","null"]},"logoUrl":{"type":["string","null"],"format":"uri"},"imageUrl":{"type":["string","null"],"format":"uri"},"category":{"$ref":"#/components/schemas/Category"},"tags":{"type":"array","items":{"$ref":"#/components/schemas/Tag"}},"listedAt":{"type":["string","null"],"format":"date-time"},"featured":{"type":"boolean"},"verification":{"type":"object","required":["badgeVerified","badgeVerifiedAt"],"properties":{"badgeVerified":{"type":"boolean"},"badgeVerifiedAt":{"type":["string","null"],"format":"date-time"}}}}},"Category":{"type":"object","required":["slug","name","liveToolCount"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"liveToolCount":{"type":"integer","minimum":0}}},"Tag":{"type":"object","required":["slug","name"],"properties":{"slug":{"type":"string"},"name":{"type":"string"}}},"Pagination":{"type":"object","required":["nextCursor","hasMore","totalCount"],"properties":{"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"},"totalCount":{"type":"integer","minimum":0}}},"ToolListResponse":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","required":["items","pagination"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Tool"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"meta":{"$ref":"#/components/schemas/ApiMeta"}}},"ToolResponse":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/Tool"},"meta":{"$ref":"#/components/schemas/ApiMeta"}}},"CategoryListResponse":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Category"}},"meta":{"$ref":"#/components/schemas/ApiMeta"}}},"TagListResponse":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Tag"}},"meta":{"$ref":"#/components/schemas/ApiMeta"}}},"ProductDraftInput":{"type":"object","required":["name","headline","description","websiteUrl"],"properties":{"name":{"type":"string","minLength":1,"maxLength":160},"headline":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","minLength":200,"maxLength":2000},"websiteUrl":{"type":"string","format":"uri","maxLength":2000},"logoUrl":{"type":"string","format":"uri","maxLength":1000,"description":"Optional. Uses the product favicon when omitted."},"screenshotUrls":{"type":"array","minItems":1,"maxItems":4,"items":{"type":"string","format":"uri","maxLength":2000},"description":"Optional. Uses the product Open Graph image when omitted. Returns 422 when a screenshot and logo cannot both be resolved."},"category":{"type":"string","minLength":1,"maxLength":120,"description":"Optional for private draft creation. If supplied, must be an existing ListBulb category slug. Choose a category in the editor before plan selection or submission."},"slug":{"type":"string","minLength":1,"maxLength":120}}},"DraftResponse":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","required":["slug","status","editorUrl"],"properties":{"slug":{"type":"string"},"status":{"const":"DRAFT"},"editorUrl":{"type":"string","format":"uri","description":"Absolute private editor URL."}}},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}}