Upload Attachment
Upload an evidence file and receive a URL for it. Pass that URL to POST /report/create in attachmentUrls to attach the file to a report — uploading alone does not create or modify a report.
Send either the raw file bytes with a fileName query parameter, or a multipart/form-data body with up to 10 file parts. The whole request body must be 4194304 bytes or smaller.
The file extension decides how the file is stored and served, so it must be one of: .avif, .bmp, .csv, .doc, .docx, .eml, .gif, .jpeg, .jpg, .msg, .pdf, .png, .txt, .webp. Any Content-Type header you send is ignored in favour of the extension.
Not images only: .eml and .msg messages, PDFs and documents are all accepted. Images are displayed inline on the report; other files are listed as downloadable evidence.
Overview
Upload a file to ChainPatrol and get back a URL. Pass that URL to Create Report inattachmentUrls to attach the file as
evidence.
This is a two-step flow, and the two steps are separate requests:
POST /attachment/upload— send the bytes, receive a URL.POST /report/create— include that URL inattachmentUrls.
attachmentUrls accepts any publicly
reachable URL, so if you already host your evidence somewhere we can fetch, keep passing
those links. This endpoint exists so you do not have to host them..eml and
.msg message files, PDFs, Word documents, CSVs, and plain text are all supported — see
Supported file types. Images are displayed inline on the report
in the dashboard; everything else is listed as a downloadable file that our takedown team
can forward to a registrar or host.Two ways to send a file
The endpoint accepts either shape. Pick whichever your HTTP client makes easier.Raw body
Send the file bytes as the request body and the file name as thefileName query
parameter. One file per request.
Multipart form
Sendmultipart/form-data with one or more file parts. This is what a browser form,
Postman’s file picker, or curl -F produces.
The file name comes from each part’s own filename, so the fileName query parameter is
ignored here. Non-file form fields are ignored, and the part names themselves do not
matter — send them all as file if you like.
File name handling
- The extension decides how we store and serve the file, so it has to be present and accepted. Matching is case-insensitive.
- Directory components are stripped:
../../secrets/evidence.emlis stored asevidence.eml. - Names must contain no control characters, and are length-capped — the schema above gives the limit.
- Your name is otherwise preserved as-is. That matters because it is the name shown on the
report, and the name a registrar or hosting provider sees when our takedown team forwards
the file — so
phishing-email.emlis worth more thanattachment1.eml. - Uploading two files with the same name is fine. Each upload is stored on its own path, so nothing is ever overwritten and the name you sent is what comes back.
Supported file types
The accepted extensions are enumerated in the request description above, and that list is generated from the same constants the endpoint enforces — so it is always current. The content type we serve the file with is derived from the extension, not from theContent-Type header you send, so any header your client sets is ignored. .svg and
.html are deliberately excluded: they render as active content, and files we serve should
not.
If you need a format that is not accepted, email
support@chainpatrol.io — a common workaround is to send
the file inside a supported container (a PDF export, or the raw .eml).
Limits
The request body size cap and the per-request file count are stated in the schema above. Two things it does not tell you:- The size cap applies to the whole request body, so in a multipart request all parts share one budget. For anything larger, split it across requests and attach the resulting URLs to the same report.
- Uploads are rate limited to 60 requests per minute per organization, or per API key
for keys that are not tied to one. Exceeding it returns
429.
The returned URL
Error responses
Every error returns a JSON body with a singleerror string describing what was wrong.
The statuses are listed with the responses above; two things worth calling out:
405is not in the list, because it is not a response ofPOST. The endpoint isPOSTonly, and any other method returns405 Method Not Allowed.- Retry
429and502, not400. A4xxother than429means the request itself needs fixing, and retrying it unchanged will fail the same way.
Best practices
- Upload first, report second. Nothing links the file to a report until you pass the
URL to
report.create. An uploaded file that is never referenced simply sits unused. - Attach every file to a report. Uploads are not visible in the dashboard on their own; the report is what makes them reviewable.
- Use meaningful file names. The name follows the file into the dashboard and into outbound takedown emails.
- Send
.emlrather than a screenshot of an email when you have it. The raw message carries headers, which is what registrars and email providers act on.
Notes
- There is no endpoint for listing, replacing, or deleting an upload. To correct a mistake, upload the right file and reference that URL instead; to remove evidence from a report, contact support@chainpatrol.io.
- Files are not scanned for malware. Do not treat an uploaded file as safe to open just because it came through the API.
Authorizations
Your API key. This is required by most endpoints to access our API programatically. Reach out to us at support@chainpatrol.io to get an API key for your use.
Query Parameters
File name for the uploaded bytes, including the extension (for example evidence.eml). Required for raw-body uploads, and must be supplied exactly once. Ignored for multipart requests, where each part carries its own file name.
200Body
The raw file bytes. Name the file with ?fileName=.
Response
The files were stored.
One entry per uploaded file, in request order.