{"openapi":"3.1.0","info":{"title":"Lunar Post API","version":"1.0.0","description":"Post videos and images to your customers' social accounts on a schedule. Profiles keep each customer's accounts apart; upload media or hand over a link, then schedule it with a caption per network. Every response is `{ data, error }`. MCP: /api/post/mcp"},"servers":[{"url":"https://clips.lnr.ae"}],"security":[{"bearer":[]}],"tags":[{"name":"Profiles and accounts","description":"A profile is one of your customers. Each has its own connected accounts, and posts never cross between profiles."},{"name":"Media","description":"Upload a video or image, or hand over a link to one. Every file is checked before it can be posted."},{"name":"Posts","description":"Schedule one media item to a profile's accounts with a caption per network, then follow and change the posts."},{"name":"Usage","description":"Where the workspace stands against its Lunar Post plan this month."}],"paths":{"/api/post/v1/profiles":{"get":{"operationId":"listProfiles","summary":"List profiles","description":"The workspace's live profiles, newest first. Find one by your own id with `externalRef`; add `includeArchived=true` to see archived ones too.\n\nMCP tool: `list_profiles`.","tags":["Profiles and accounts"],"x-scope":"read","parameters":[{"name":"externalRef","in":"query","required":false,"description":"Only the profile with this externalRef.","schema":{"type":"string","maxLength":200}},{"name":"includeArchived","in":"query","required":false,"description":"Include archived profiles. Default false.","schema":{"type":"boolean"}},{"name":"limit","in":"query","required":false,"description":"How many to return. Default 100.","schema":{"type":"integer","minimum":1,"maximum":250}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"profiles":[{"id":"7c9e6679-7425-40de-944b-e07fc1f90ae7","name":"Acme Coffee","externalRef":"cus_8841","createdAt":"2026-11-14T09:12:00.000Z","archivedAt":null}]},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createProfile","summary":"Create a profile","description":"Adds a profile for one of your customers. Uses one of the plan's profiles, and is refused with `plan_limit` when they're all in use (archive one to free it).\n\nMCP tool: `create_profile`.","tags":["Profiles and accounts"],"x-scope":"write","parameters":[{"name":"preview","in":"query","required":false,"description":"`1` runs every check and returns `{ preview }` (what would happen) without changing anything.","schema":{"type":"string","enum":["1"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80,"description":"The customer's name, shown on the connect page."},"externalRef":{"type":["string","null"],"maxLength":200,"description":"Your own id for this customer. Unique among live profiles; null clears it."}},"required":["name"],"additionalProperties":false},"example":{"name":"Acme Coffee","externalRef":"cus_8841"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"id":"7c9e6679-7425-40de-944b-e07fc1f90ae7","name":"Acme Coffee","externalRef":"cus_8841","createdAt":"2026-11-14T09:12:00.000Z","archivedAt":null},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/post/v1/profiles/{id}":{"get":{"operationId":"getProfile","summary":"Get a profile","description":"One profile with its accounts. Only accounts with status `connected` can post; `needs_reauth` means the customer has to connect it again.\n\nMCP tool: `get_profile`.","tags":["Profiles and accounts"],"x-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"The profile's id, from List profiles or Create a profile.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"id":"7c9e6679-7425-40de-944b-e07fc1f90ae7","name":"Acme Coffee","externalRef":"cus_8841","createdAt":"2026-11-14T09:12:00.000Z","archivedAt":null,"accounts":[{"id":"c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b","platform":"instagram","handle":"acmecoffee","avatarUrl":"https://cdn.example.com/avatars/acme.jpg","status":"connected","timezone":"Asia/Dubai"},{"id":"d7e8f9a0-1b2c-4d3e-8f4a-5b6c7d8e9f0a","platform":"tiktok","handle":"acme.coffee","avatarUrl":null,"status":"connected","timezone":"Asia/Dubai"}]},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateProfile","summary":"Update a profile","description":"Renames a live profile, or changes or clears its externalRef. Send at least one of the two.","tags":["Profiles and accounts"],"x-scope":"write","parameters":[{"name":"id","in":"path","required":true,"description":"The profile's id, from List profiles or Create a profile.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80,"description":"The customer's name, shown on the connect page."},"externalRef":{"type":["string","null"],"maxLength":200,"description":"Your own id for this customer. Unique among live profiles; null clears it."}},"additionalProperties":false},"example":{"name":"Acme Coffee Roasters"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"id":"7c9e6679-7425-40de-944b-e07fc1f90ae7","name":"Acme Coffee Roasters","externalRef":"cus_8841","createdAt":"2026-11-14T09:12:00.000Z","archivedAt":null},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/post/v1/profiles/{id}/archive":{"post":{"operationId":"archiveProfile","summary":"Archive a profile","description":"Archives a profile so it frees one of the plan's profiles. Refused while it has posts waiting to go out: cancel them first. Archiving an archived profile changes nothing.","tags":["Profiles and accounts"],"x-scope":"write","parameters":[{"name":"id","in":"path","required":true,"description":"The profile's id, from List profiles or Create a profile.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"id":"7c9e6679-7425-40de-944b-e07fc1f90ae7","name":"Acme Coffee","externalRef":"cus_8841","createdAt":"2026-11-14T09:12:00.000Z","archivedAt":"2026-11-18T12:00:00.000Z"},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/post/v1/profiles/{id}/accounts":{"get":{"operationId":"listProfileAccounts","summary":"List a profile's accounts","description":"The profile's connected accounts: the ids Schedule a post takes in `accountIds`, with network, handle, status and timezone.\n\nMCP tool: `list_accounts`.","tags":["Profiles and accounts"],"x-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"The profile's id, from List profiles or Create a profile.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"accounts":[{"id":"c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b","platform":"instagram","handle":"acmecoffee","avatarUrl":"https://cdn.example.com/avatars/acme.jpg","status":"connected","timezone":"Asia/Dubai"},{"id":"d7e8f9a0-1b2c-4d3e-8f4a-5b6c7d8e9f0a","platform":"tiktok","handle":"acme.coffee","avatarUrl":null,"status":"connected","timezone":"Asia/Dubai"}]},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/post/v1/profiles/{id}/connect-links":{"post":{"operationId":"createConnectLink","summary":"Create a connect link","description":"A short-lived link to a Lunar Post page where your customer connects their accounts, signing in on each network's own page. Send them there; when they finish they go to `returnUrl` with `?status=connected|cancelled|failed&profile=<id>`. Anyone holding the link can connect accounts to this profile until it expires.\n\nMCP tool: `create_connect_link`.","tags":["Profiles and accounts"],"x-scope":"write","parameters":[{"name":"id","in":"path","required":true,"description":"The profile's id, from List profiles or Create a profile.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"returnUrl":{"type":"string","maxLength":2000,"description":"Full https address on a public host name."},"networks":{"type":"array","items":{"type":"string","enum":["instagram","tiktok","linkedin","facebook","threads","youtube","pinterest"]},"maxItems":10,"description":"Networks the page offers. All of them when left out."},"ttlSeconds":{"type":"integer","minimum":300,"maximum":86400,"description":"How long the link works. Default 3600 (an hour)."}},"required":["returnUrl"],"additionalProperties":false},"example":{"returnUrl":"https://app.example.com/settings/social?customer=cus_8841","networks":["instagram","tiktok"]}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"url":"https://post.lnr.ae/connect/eyJ2IjoxLCJ3b3Jrc3BhY2VJZCI6Ii4uLiJ9.7c9e6679","expiresAt":"2026-11-14T11:12:00.000Z"},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/post/v1/media/uploads":{"post":{"operationId":"createUpload","summary":"Create an upload URL","description":"Step one of an upload: returns a signed `uploadUrl`, the `headers` to send and the `storagePath`. PUT the file's bytes to `uploadUrl` with those headers within 2 hours, then call Complete an upload. Videos: MP4 or MOV up to 1 GB. Images: JPEG, PNG or WebP up to 20 MB.\n\nMCP tool: `create_upload_url`.","tags":["Media"],"x-scope":"write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fileName":{"type":"string","minLength":1,"maxLength":200,"description":"With its extension, e.g. launch.mp4."},"contentType":{"type":"string","enum":["video/mp4","video/quicktime","image/jpeg","image/png","image/webp"]},"sizeBytes":{"type":"integer","minimum":1,"description":"The file's exact size in bytes."},"profileId":{"type":["string","null"],"format":"uuid","description":"File it under this profile (only its posts can use it). Leave out to share it across your profiles."}},"required":["fileName","contentType","sizeBytes"],"additionalProperties":false},"example":{"fileName":"cold-brew-launch.mp4","contentType":"video/mp4","sizeBytes":48211904,"profileId":"7c9e6679-7425-40de-944b-e07fc1f90ae7"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"storagePath":"1b4e28ba-2fa1-41d2-883f-0016d3cca427/post/7c9e6679-7425-40de-944b-e07fc1f90ae7/0f7e5c1a-3b2d-4e6f-8a9b-1c2d3e4f5a6b-cold-brew-launch.mp4","uploadUrl":"https://storage.example.com/object/upload/sign/media/…?token=…","method":"PUT","headers":{"Content-Type":"video/mp4"},"expiresAt":"2026-11-14T12:02:00.000Z","kind":"video"},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/post/v1/media/uploads/complete":{"post":{"operationId":"completeUpload","summary":"Complete an upload","description":"Step two, after the PUT: checks the stored file's real size and type (removing it if they don't match what you declared), saves it as media and starts its content check. `contentCheck` stays `pending` until the check is done, usually under a minute.\n\nMCP tool: `complete_upload`.","tags":["Media"],"x-scope":"write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"storagePath":{"type":"string","maxLength":400},"sizeBytes":{"type":"integer","minimum":1},"title":{"type":"string","maxLength":200,"description":"A name for the media; also the YouTube title when the post has none."}},"required":["storagePath","sizeBytes"],"additionalProperties":false},"example":{"storagePath":"1b4e28ba-2fa1-41d2-883f-0016d3cca427/post/7c9e6679-7425-40de-944b-e07fc1f90ae7/0f7e5c1a-3b2d-4e6f-8a9b-1c2d3e4f5a6b-cold-brew-launch.mp4","sizeBytes":48211904,"title":"Cold brew launch"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"id":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","profileId":"7c9e6679-7425-40de-944b-e07fc1f90ae7","kind":"video","source":"upload","name":"cold-brew-launch.mp4","title":"Cold brew launch","createdAt":"2026-11-14T10:02:00.000Z","contentCheck":"pending"},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/post/v1/media/import":{"post":{"operationId":"importMedia","summary":"Import from a link","description":"Fetches a video or image from a public https link, reads its real type from the file itself, caps its size while it downloads, saves it as media and starts its content check. Links to private or local addresses are refused.\n\nMCP tool: `import_media_from_url`.","tags":["Media"],"x-scope":"write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":2000,"description":"Public https link to the file itself."},"profileId":{"type":["string","null"],"format":"uuid","description":"File it under this profile (only its posts can use it). Leave out to share it across your profiles."},"title":{"type":"string","maxLength":200,"description":"A name for the media; also the YouTube title when the post has none."},"fileName":{"type":"string","maxLength":200,"description":"Name to store it under. Taken from the link when left out."}},"required":["url"],"additionalProperties":false},"example":{"url":"https://cdn.example.com/renders/cold-brew-launch.mp4","profileId":"7c9e6679-7425-40de-944b-e07fc1f90ae7","title":"Cold brew launch"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"id":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","profileId":"7c9e6679-7425-40de-944b-e07fc1f90ae7","kind":"video","source":"link","name":"cold-brew-launch.mp4","title":"Cold brew launch","createdAt":"2026-11-14T10:02:00.000Z","contentCheck":"pending"},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/post/v1/media":{"get":{"operationId":"listMedia","summary":"List media","description":"The workspace's Lunar Post media, newest first, with each item's `contentCheck`: `pending`, `passed` (can be posted) or `held` (waiting for a content review, can't be posted). Pages with `nextCursor`.\n\nMCP tool: `list_media`.","tags":["Media"],"x-scope":"read","parameters":[{"name":"profileId","in":"query","required":false,"description":"A profile id, or `shared` for media shared across profiles.","schema":{"type":"string"}},{"name":"kind","in":"query","required":false,"description":"Only videos or only images.","schema":{"type":"string","enum":["video","image"]}},{"name":"limit","in":"query","required":false,"description":"How many to return. Default 20.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"The nextCursor from the previous page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"media":[{"id":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","profileId":"7c9e6679-7425-40de-944b-e07fc1f90ae7","kind":"video","source":"upload","name":"cold-brew-launch.mp4","title":"Cold brew launch","createdAt":"2026-11-14T10:02:00.000Z","contentCheck":"passed"}],"nextCursor":null},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/post/v1/media/{id}":{"get":{"operationId":"getMedia","summary":"Get a media item","description":"One media item with its content check. Poll it after an upload until `contentCheck` is `passed`.","tags":["Media"],"x-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"The media item's id, from Complete an upload, Import from a link or List media.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"id":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","profileId":"7c9e6679-7425-40de-944b-e07fc1f90ae7","kind":"video","source":"upload","name":"cold-brew-launch.mp4","title":"Cold brew launch","createdAt":"2026-11-14T10:02:00.000Z","contentCheck":"passed"},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteMedia","summary":"Delete a media item","description":"Deletes the file. Refused while posts using it are waiting to go out: cancel them first. Posts that already went out keep their history.","tags":["Media"],"x-scope":"write","parameters":[{"name":"id","in":"path","required":true,"description":"The media item's id, from Complete an upload, Import from a link or List media.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"id":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","deleted":true},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/post/v1/posts":{"post":{"operationId":"schedulePost","summary":"Schedule a post","description":"Posts one media item to one or more of a profile's accounts: `when` is a time, `\"now\"` or `\"next_free_slot\"`. Each account uses one of this month's posts, reserved before anything is written and refused with `plan_limit` at the limit. Keys act as editors: in a workspace that reviews posts, they wait for the owner's approval (`awaitingApproval`).\n\nMCP tool: `schedule_post`.","tags":["Posts"],"x-scope":"write","parameters":[{"name":"preview","in":"query","required":false,"description":"`1` runs every check and returns `{ preview }` (what would happen) without changing anything.","schema":{"type":"string","enum":["1"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"mediaId":{"type":"string","format":"uuid","description":"Media whose content check passed."},"profileId":{"type":["string","null"],"format":"uuid","description":"The profile whose accounts you post to. Null or absent: the workspace's own accounts."},"accountIds":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":25,"description":"All from the same profile. Each account counts as one post."},"captions":{"type":"object","properties":{"instagram":{"type":"object","properties":{"caption":{"type":"string","maxLength":5000,"description":"The post text. Instagram and TikTok allow 2,200 characters, LinkedIn 3,000, Threads 500."},"hashtags":{"type":"array","items":{"type":"string","maxLength":100},"maxItems":30,"description":"With or without #."}},"required":["caption"],"additionalProperties":false},"tiktok":{"type":"object","properties":{"caption":{"type":"string","maxLength":5000,"description":"The post text. Instagram and TikTok allow 2,200 characters, LinkedIn 3,000, Threads 500."},"hashtags":{"type":"array","items":{"type":"string","maxLength":100},"maxItems":30,"description":"With or without #."}},"required":["caption"],"additionalProperties":false},"linkedin":{"type":"object","properties":{"caption":{"type":"string","maxLength":5000,"description":"The post text. Instagram and TikTok allow 2,200 characters, LinkedIn 3,000, Threads 500."},"hashtags":{"type":"array","items":{"type":"string","maxLength":100},"maxItems":30,"description":"With or without #."}},"required":["caption"],"additionalProperties":false},"facebook":{"type":"object","properties":{"caption":{"type":"string","maxLength":5000,"description":"The post text. Instagram and TikTok allow 2,200 characters, LinkedIn 3,000, Threads 500."},"hashtags":{"type":"array","items":{"type":"string","maxLength":100},"maxItems":30,"description":"With or without #."}},"required":["caption"],"additionalProperties":false},"threads":{"type":"object","properties":{"caption":{"type":"string","maxLength":5000,"description":"The post text. Instagram and TikTok allow 2,200 characters, LinkedIn 3,000, Threads 500."},"hashtags":{"type":"array","items":{"type":"string","maxLength":100},"maxItems":30,"description":"With or without #."}},"required":["caption"],"additionalProperties":false},"youtube":{"type":"object","properties":{"caption":{"type":"string","maxLength":5000,"description":"The post text. Instagram and TikTok allow 2,200 characters, LinkedIn 3,000, Threads 500."},"hashtags":{"type":"array","items":{"type":"string","maxLength":100},"maxItems":30,"description":"With or without #."}},"required":["caption"],"additionalProperties":false},"pinterest":{"type":"object","properties":{"caption":{"type":"string","maxLength":5000,"description":"The post text. Instagram and TikTok allow 2,200 characters, LinkedIn 3,000, Threads 500."},"hashtags":{"type":"array","items":{"type":"string","maxLength":100},"maxItems":30,"description":"With or without #."}},"required":["caption"],"additionalProperties":false}},"additionalProperties":false,"description":"One caption per network."},"caption":{"type":"object","properties":{"caption":{"type":"string","maxLength":5000,"description":"The post text. Instagram and TikTok allow 2,200 characters, LinkedIn 3,000, Threads 500."},"hashtags":{"type":"array","items":{"type":"string","maxLength":100},"maxItems":30,"description":"With or without #."}},"required":["caption"],"additionalProperties":false,"description":"The caption for every network without an entry in captions."},"when":{"type":"string","description":"\"now\", \"next_free_slot\" (each account's next posting time) or an ISO 8601 time with offset at least 2 minutes ahead."},"title":{"type":"string","maxLength":100,"description":"YouTube and Pinterest title."},"sendForReview":{"type":"boolean","description":"Hold the posts for the workspace owner's approval."},"aiGenerated":{"type":"boolean","description":"Label the post as AI-generated where the network supports it (YouTube, TikTok)."},"tiktok":{"type":"object","properties":{"privacyLevel":{"type":"string","maxLength":40},"allowComments":{"type":"boolean"},"allowDuet":{"type":"boolean"},"allowStitch":{"type":"boolean"},"promotesOwnBrand":{"type":"boolean"},"musicUsageConsent":{"type":"boolean"}},"additionalProperties":false},"youtube":{"type":"object","properties":{"madeForKids":{"type":"boolean"}},"required":["madeForKids"],"additionalProperties":false}},"required":["mediaId","accountIds","when"],"additionalProperties":false},"example":{"mediaId":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","profileId":"7c9e6679-7425-40de-944b-e07fc1f90ae7","accountIds":["c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b","d7e8f9a0-1b2c-4d3e-8f4a-5b6c7d8e9f0a"],"captions":{"instagram":{"caption":"Cold brew is back. Twelve hours steeped, zero bitterness.","hashtags":["coldbrew","acmecoffee"]},"tiktok":{"caption":"POV: your coffee took 12 hours so you don't have to wait","hashtags":["coldbrew"]}},"when":"2026-11-20T09:00:00+04:00","aiGenerated":true}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"postIds":["3f8f6c1e-2b4a-4c3d-9e5f-1a2b3c4d5e6f","8b2d4f6a-1c3e-4a5b-9d7f-0e2a4c6b8d1f"],"awaitingApproval":false,"usage":{"used":14,"limit":50}},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"listPosts","summary":"List posts","description":"Lunar Post posts, latest scheduled first, with status, live link and failure reason. Filter by profile, account, network, status and a window on the scheduled time.\n\nMCP tool: `list_posts`.","tags":["Posts"],"x-scope":"read","parameters":[{"name":"profileId","in":"query","required":false,"description":"A profile id, or `unprofiled` for the workspace's own accounts.","schema":{"type":"string"}},{"name":"accountId","in":"query","required":false,"description":"Only this account's posts.","schema":{"type":"string","format":"uuid"}},{"name":"platform","in":"query","required":false,"description":"Only this network.","schema":{"type":"string","enum":["instagram","tiktok","linkedin","facebook","threads","youtube","pinterest"]}},{"name":"status","in":"query","required":false,"description":"Only posts in this status.","schema":{"type":"string","enum":["draft","ready","approved","scheduled","publishing","awaiting_creator","published","failed","cancelled"]}},{"name":"from","in":"query","required":false,"description":"Scheduled at or after (ISO 8601 with offset).","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"description":"Scheduled before (ISO 8601 with offset).","schema":{"type":"string","format":"date-time"}},{"name":"limit","in":"query","required":false,"description":"How many to return. Default 20.","schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"posts":[{"id":"3f8f6c1e-2b4a-4c3d-9e5f-1a2b3c4d5e6f","platform":"instagram","accountId":"c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b","status":"scheduled","caption":"Cold brew is back. Twelve hours steeped, zero bitterness.","hashtags":["coldbrew","acmecoffee"],"scheduledFor":"2026-11-20T05:00:00.000Z","publishedAt":null,"externalUrl":null,"failureReason":null,"videoId":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","mediaId":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","profileId":"7c9e6679-7425-40de-944b-e07fc1f90ae7"}]},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/post/v1/posts/{id}":{"get":{"operationId":"getPost","summary":"Get a post","description":"One post: its status, when it goes or went out, the live link once published (`externalUrl`) and `failureReason` if it failed.\n\nMCP tool: `get_post`.","tags":["Posts"],"x-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"The post's id, from Schedule a post (postIds) or List posts.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"id":"3f8f6c1e-2b4a-4c3d-9e5f-1a2b3c4d5e6f","platform":"instagram","accountId":"c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b","status":"published","caption":"Cold brew is back. Twelve hours steeped, zero bitterness.","hashtags":["coldbrew","acmecoffee"],"scheduledFor":"2026-11-20T05:00:00.000Z","publishedAt":"2026-11-20T05:00:41.000Z","externalUrl":"https://www.instagram.com/reel/C9xYz12AbCd/","failureReason":null,"videoId":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","mediaId":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","profileId":"7c9e6679-7425-40de-944b-e07fc1f90ae7"},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updatePost","summary":"Update a post","description":"Moves a post that hasn't gone out and/or changes its caption and hashtags. In a workspace that reviews posts, changing an approved post sends it back for approval.\n\nMCP tool: `update_post`.","tags":["Posts"],"x-scope":"write","parameters":[{"name":"id","in":"path","required":true,"description":"The post's id, from Schedule a post (postIds) or List posts.","schema":{"type":"string","format":"uuid"}},{"name":"preview","in":"query","required":false,"description":"`1` runs every check and returns `{ preview }` (what would happen) without changing anything.","schema":{"type":"string","enum":["1"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"when":{"type":"string","description":"ISO 8601 with offset, at least 2 minutes ahead."},"caption":{"type":"string","maxLength":5000},"hashtags":{"type":"array","items":{"type":"string","maxLength":100},"maxItems":30}},"additionalProperties":false},"example":{"when":"2026-11-21T09:00:00+04:00"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"id":"3f8f6c1e-2b4a-4c3d-9e5f-1a2b3c4d5e6f","platform":"instagram","accountId":"c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b","status":"scheduled","caption":"Cold brew is back. Twelve hours steeped, zero bitterness.","hashtags":["coldbrew","acmecoffee"],"scheduledFor":"2026-11-21T05:00:00.000Z","publishedAt":null,"externalUrl":null,"failureReason":null,"videoId":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","mediaId":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","profileId":"7c9e6679-7425-40de-944b-e07fc1f90ae7"},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"cancelPost","summary":"Cancel a post","description":"Cancels a post that hasn't gone out. It won't be posted, and the post it used comes back to its month's allowance.\n\nMCP tool: `cancel_post`.","tags":["Posts"],"x-scope":"write","parameters":[{"name":"id","in":"path","required":true,"description":"The post's id, from Schedule a post (postIds) or List posts.","schema":{"type":"string","format":"uuid"}},{"name":"preview","in":"query","required":false,"description":"`1` runs every check and returns `{ preview }` (what would happen) without changing anything.","schema":{"type":"string","enum":["1"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"id":"3f8f6c1e-2b4a-4c3d-9e5f-1a2b3c4d5e6f","platform":"instagram","accountId":"c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b","status":"cancelled","caption":"Cold brew is back. Twelve hours steeped, zero bitterness.","hashtags":["coldbrew","acmecoffee"],"scheduledFor":"2026-11-20T05:00:00.000Z","publishedAt":null,"externalUrl":null,"failureReason":null,"videoId":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","mediaId":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","profileId":"7c9e6679-7425-40de-944b-e07fc1f90ae7"},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/post/v1/posts/{id}/retry":{"post":{"operationId":"retryPost","summary":"Retry a post","description":"Sends a failed post again, about 3 minutes later. If the failure reason says the account needs reconnecting, send the customer a new connect link first.\n\nMCP tool: `retry_post`.","tags":["Posts"],"x-scope":"write","parameters":[{"name":"id","in":"path","required":true,"description":"The post's id, from Schedule a post (postIds) or List posts.","schema":{"type":"string","format":"uuid"}},{"name":"preview","in":"query","required":false,"description":"`1` runs every check and returns `{ preview }` (what would happen) without changing anything.","schema":{"type":"string","enum":["1"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"id":"3f8f6c1e-2b4a-4c3d-9e5f-1a2b3c4d5e6f","platform":"instagram","accountId":"c4a1e2f3-5b6d-4e7f-8a9b-0c1d2e3f4a5b","status":"scheduled","caption":"Cold brew is back. Twelve hours steeped, zero bitterness.","hashtags":["coldbrew","acmecoffee"],"scheduledFor":"2026-11-20T05:08:00.000Z","publishedAt":null,"externalUrl":null,"failureReason":null,"videoId":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","mediaId":"9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d","profileId":"7c9e6679-7425-40de-944b-e07fc1f90ae7"},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/post/v1/posts/{id}/approve":{"post":{"operationId":"approvePost","summary":"Approve a post","description":"Approves a post waiting for review (status `ready`), which schedules it. Needs a key with the approve scope, which only the workspace owner can make.\n\nMCP tool: `approve_post`.","tags":["Posts"],"x-scope":"approve","parameters":[{"name":"id","in":"path","required":true,"description":"The post's id, from Schedule a post (postIds) or List posts.","schema":{"type":"string","format":"uuid"}},{"name":"preview","in":"query","required":false,"description":"`1` runs every check and returns `{ preview }` (what would happen) without changing anything.","schema":{"type":"string","enum":["1"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"id":"3f8f6c1e-2b4a-4c3d-9e5f-1a2b3c4d5e6f","status":"scheduled","scheduledFor":"2026-11-20T05:00:00.000Z"},"error":null}}}},"400":{"description":"invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/post/v1/usage":{"get":{"operationId":"getUsage","summary":"Get usage","description":"The plan, this month's posts used against its limit (one post per account posted to, counted by UTC calendar month) and live profiles against the plan's profiles. Limits are hard: past them, writes are refused with `plan_limit`. `plan` is `trial`, `starter`, `growth`, `scale` or `none` (the trial ended without a paid plan: everything stays readable, but posting, uploads and new profiles are refused until a plan is chosen). `trialEndsAt` is when the 14-day trial ends; `renewsAt` is the paid plan's next renewal, and `endsAt` is set instead when it's cancelled.\n\nMCP tool: `get_usage`.","tags":["Usage"],"x-scope":"read","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{},"error":{"type":"null"}}},"example":{"data":{"plan":"trial","period":"2026-11-01","posts":{"used":12,"limit":50},"profiles":{"used":2,"limit":3},"trialEndsAt":"2026-11-28T10:00:00.000Z","renewsAt":null,"endsAt":null},"error":null}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"An API key for the workspace, sent as a bearer token."}},"schemas":{"Error":{"type":"object","required":["data","error"],"properties":{"data":{"type":"null"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthorized","forbidden","not_found","invalid_input","invalid_json","payload_too_large","unsupported_media_type","method_not_allowed","rate_limited","plan_required","plan_limit","internal"]},"message":{"type":"string","description":"Plain English, safe to show a person or an AI."}}}}}}}}