Upload a file
The request body is the file itself, up to 20 MB. Send the real Content-Type, since the stored type comes from it. Returns the id to send in a message’s attachments, and the size and type it stored. The name is cut to 200 characters. HTML, XHTML, SVG and XSLT files upload, but a message that attaches one is refused. A message can be attachments alone with an empty body, and threads return each attachment with a download url.
POST
/uploadsAuthorization
AuthorizationBearer token · headerrequiredA MEDIAN_KEY from Settings under API. It starts with `median_key_` and stays on your server. The tool endpoint routes also accept an OAuth access token (`median_oat_`) from `median login` or an MCP client, acting as the person who approved it. The messaging routes accept only a Median key.
Query parameters
namestringrequiredThe file's name, as the team will see it.
Request body
requiredapplication/octet-streamThe file's bytes. Send the real content type.
string<binary>Responses
200The stored file.
attachmentIdstringrequirednamestringrequiredsizeintegerrequiredtypestringrequired400`invalid_request`: the `name` query parameter is missing. `empty_file`: the body is empty. `file_too_big`: the file is over 20 MB.
errorobjectrequiredShow propertiesHide properties
codestringrequiredBranch on this rather than on the message.
messagestringrequired401`missing_api_key`: no bearer token. `invalid_api_key`: the key matches no organization or was revoked. `publishable_key`: a `median_pk_` key was sent. An OAuth access token is refused here with `invalid_api_key`.
errorobjectrequiredShow propertiesHide properties
codestringrequiredBranch on this rather than on the message.
messagestringrequired429The organization's API allowance for this class of request is used up. Wait the `Retry-After` header's seconds. Limits depend on the plan. See [rate limits](/api/errors-and-limits#rate-limits).
errorobjectrequiredShow propertiesHide properties
codestringrequiredBranch on this rather than on the message.
messagestringrequiredRequest
curl -X POST "https://api.median.sh/v1/uploads?name=receipt.pdf" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/octet-stream" \
-d '"<binary>"'const response = await fetch("https://api.median.sh/v1/uploads?name=receipt.pdf", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/octet-stream"
},
body: JSON.stringify("<binary>")
});Response
{
"attachmentId": "kg2f...",
"name": "receipt.pdf",
"size": 182044,
"type": "application/pdf"
}{
"error": {
"code": "file_too_big",
"message": "Files have to be 20 MB or smaller."
}
}{
"error": {
"code": "invalid_api_key",
"message": "That Median key does not match any organization. Copy the median_key_ key again from Settings under API."
}
}{
"error": {
"code": "rate_limited",
"message": "Your organization's API allowance is temporarily full. Please retry shortly."
}
}