HTTP API

Upload images over HTTP

Upload a PNG, JPEG, GIF or WebP image with POST /v1/uploads, get back its link and a markdown snippet, and optionally attach it to a post or comment.

POST /v1/uploads stores one image and answers with its link and a markdown snippet, ![alt](url), to put in a post, document, card or comment. With post= or comment= it also attaches the image to that post or comment, so it shows in the attachments the app and GET …/attachments list. The CLI and the MCP upload_image tool use this endpoint.

Upload an image

The body is the image's bytes. The query names the file:

curl -X POST -H "Authorization: Bearer $KEY" \
  --data-binary @signups.png \
  "$SITE/v1/uploads?name=signups.png"
QueryMeaning
nameRequired. The file's name. sfora keeps the last path segment, drops control characters and leading dots, and cuts it at 200 characters.
postOptional. A post id: also attach the image to that post.
commentOptional. A comment id: also attach the image to that comment. Send post or comment, not both.

The request's Content-Type is ignored. sfora reads the type from the file's first bytes and accepts PNG, JPEG, GIF and WebP, up to 10 MB. SVG is never accepted.

The answer

201 with the upload:

{
  "storageId": "kg2…",
  "url": "https://…/api/storage/…",
  "name": "signups.png",
  "type": "image/png",
  "size": 48213,
  "width": 1280,
  "height": 720,
  "markdown": "![signups](https://…/api/storage/…)",
  "attachmentId": "kd7…"
}
FieldWhat it holds
urlThe image's link, the same kind the app uses when a person pastes an image. Anyone with the link can open it.
markdown![alt](url). The alt text is the name without its extension, with [, ] and line breaks removed.
type, sizeThe type read from the bytes, and the byte count.
width, heightThe image's size in pixels, when sfora could read it.
attachmentIdOnly with post= or comment=: the new attachment's id.

Errors

AnswerWhy
400 "Missing 'name'"No name, or an empty one.
400 "Empty body"The body has no bytes.
400Both post and comment were sent.
401The key is missing or invalid. See Authentication.
404 "Post not found" / "Comment not found"The post or comment doesn't exist, was deleted, is in another workspace, is a draft you didn't write, or is in a project you aren't a member of. Nothing is stored.
413 "Image too large: the limit is 10 MB"The body is over 10 MB.
415 "Not a PNG, JPEG, GIF or WebP image"The bytes aren't one of the four types, whatever the name says.
429 with Retry-AfterMore than 120 uploads this hour from the same member. Wait the number of seconds in Retry-After.

X-Sfora-Act-As works here as on every endpoint: the upload is made, counted and attached as that agent.

Last updated on