Home

Uploading Files

Use POST /v3/Files to upload a file and attach it to a client record or work item. Every upload must be linked to exactly one entity at the time of upload — there is no way to attach a file to multiple records in a single request.

Overview

/v3/Files is the only Karbon endpoint that does not accept JSON. Instead, it takes a multipart/form-data body: the binary file as one part, plus a single form field naming the target record. On success it returns the created file’s identifier and metadata.

Authentication uses the same Authorization and AccessKey headers as every other endpoint — see the Authentication guide if you don’t have these set up yet.

POST https://api.karbonhq.com/v3/Files
Authorization: Bearer {token}
AccessKey: {key}
Content-Type: multipart/form-data

Supported file types

The endpoint accepts most everyday document and media formats — PDFs, plain text, CSV, Word and Excel files, images, and similar. Executables, scripts, raw HTML and a handful of other unsafe formats are rejected. If you need to upload a file in a blocked format, add it to a .zip archive and upload that instead.

Request body

Form fieldTypeRequiredNotes
filebinaryyesThe file to upload, attached as a multipart file part.
contact_keysstring*A single Contact key.
organization_keysstring*A single Organization key.
client_group_keysstring*A single Client Group key.
workitem_keysstring*A single Work Item key.
integration_task_keystring*A single Integration Task key.

* Exactly one link field must be supplied. Despite the plural names, each link field accepts only one key.

Filename and MIME type

You do not need to send the filename or MIME type as separate form fields. Karbon reads both from the file part itself:

  • Filename — the filename="…" parameter on the file part’s Content-Disposition header (set automatically by every standard HTTP client when you attach a file from disk).
  • MIME type — the file part’s own Content-Type header. If absent, Karbon infers the MIME type from the filename extension; if that also fails, the file is stored as application/octet-stream.

Example

curl -X POST https://api.karbonhq.com/v3/Files \
  -H "Authorization: Bearer {token}" \
  -H "AccessKey: {key}" \
  -F "file=@./proposal.pdf;type=application/pdf" \
  -F "workitem_keys=RXq4mD62PXg"

This uploads proposal.pdf and links it to a single work item.

Response

201 Created

{
  "@odata.context": "https://api.karbonhq.com/v3/$metadata#Files/$entity",
  "Id": "2S3RNjkR66Ln",
  "Name": "proposal.pdf",
  "MimeType": "application/pdf",
  "Size": "334565"
}

Errors

StatusMeaningCommon cause
400 Bad RequestNo file was includedThe request was missing a multipart part named file, or the part had no filename= on its Content-Disposition header.
400 Bad RequestNo entity keys were providedNone of the link fields were populated. Exactly one is required.
400 Bad RequestCannot link to more than one entityMore than one link field was populated, or a link field contained more than one key. Only one entity may be linked per upload.
401 UnauthorizedMissing or invalid bearer tokenSee Authentication.
429 Too Many RequestsRate limit exceededSee Rate limits.
500 Internal Server ErrorUnsupported file type, or an unexpected server errorRetry once; if it persists, contact support with the response body.

Attaching to multiple records

To link the same file to several records, upload it once per record — each request returns its own Id. There is no endpoint for adding a link to an existing file after the fact.

Downloading files

This guide covers the upload path only. To download a previously uploaded file, see GET /v3/Files with a download token issued by GET /v3/FileList/{EntityType}.

Overriding filename or MIME type

If the file on disk has a misleading name or its detected MIME type is wrong, most HTTP clients let you override what’s sent on the file part. In curl, append filename= and type= to the -F value:

curl -F "file=@./report.bin;filename=q4-summary.pdf;type=application/pdf" ...

The same controls exist in most HTTP client libraries. In Python requests, pass a tuple: files={"file": ("q4-summary.pdf", open(path, "rb"), "application/pdf")}. In JavaScript fetch, construct a File or Blob with the desired name and MIME type.