DEVELOPER GUIDE
Beta
Attachments
- Overview
- Listing what’s already attached
- Uploading a document
- Downloading a document
- Removing a document
- Permissions
Overview
An attachment is a supporting document — a screenshot, a source PDF, whatever backs up a finding’s review. You upload one, download it back, and remove it when it’s no longer relevant. This guide covers all three, plus the shape and limits of each.
A finding only ever signals hasAttachments (a boolean); the actual metadata and download links live at their own address, covered here.
Listing what’s already attached
curl -X GET "https://api.pointservices.com/riskinsight-services-ws/resources/v1/findings/workflows/wfpop_0000000000002082611/findings/fndg_0000000000006051384/attachments" \
-H "Authorization: Bearer your_access_token_here"
{
"workflowId": "wfpop_0000000000002082611",
"findingId": "fndg_0000000000006051384",
"attachments": [
{
"attachmentId": "attchmnt_0000000000006099213",
"name": "paystub-august.pdf",
"contentType": "application/pdf",
"modifiable": true,
"updatedAt": "2026-08-07T15:01:12Z",
"links": {
"download": {
"src": "https://api.pointservices.com/riskinsight-services-ws/resources/v1/findings/workflows/wfpop_0000000000002082611/findings/fndg_0000000000006051384/attachments/attchmnt_0000000000006099213/content"
}
}
}
],
"links": {
"self": { "href": "https://api.pointservices.com/riskinsight-services-ws/resources/v1/findings/workflows/wfpop_0000000000002082611/findings/fndg_0000000000006051384/attachments" },
"finding": { "href": "https://api.pointservices.com/riskinsight-services-ws/resources/v1/findings/workflows/wfpop_0000000000002082611/findings/fndg_0000000000006051384" }
}
}
This lists live attachments only — one you or someone else removed doesn’t reappear here in any form, and there’s no deleted flag to filter on. A finding with none returns an empty array, same as one whose hasAttachments is false.
Uploading a document
This is the one call on the whole Findings API that isn’t JSON. It’s multipart/form-data, with two parts:
curl -X POST "https://api.pointservices.com/riskinsight-services-ws/resources/v1/findings/workflows/wfpop_0000000000002082611/findings/fndg_0000000000006051384/attachments" \
-H "Authorization: Bearer your_access_token_here" \
-F "name=paystub-august.pdf" \
-F "file=@paystub-august.pdf;type=application/pdf"
name becomes the file name you’ll see later in the attachments list. file is the document’s own bytes, as a binary multipart part — set its Content-Type accurately, since it’s stored exactly as sent and republished as contentType on every later read. There’s no server-side detection to fall back on if you get it wrong.
Have curl’s -F build the multipart body for you rather than constructing it by hand — -F "file=@path;type=..." sets both the filename and the part’s Content-Type header correctly in one flag.
A file over 10 MiB (10,485,760 bytes) is rejected outright with a 400 — never silently truncated. If your integration handles large source documents, check the file size before uploading so you fail fast with a clear message instead of spending the whole upload only to have it rejected. name has its own limit too: 255 UTF-8 bytes.
The response is the finding itself, re-projected — it signals hasAttachments: true but doesn’t embed the new attachment’s metadata. Fetch the attachments list (above) afterward to get its attachmentId and download link.
Downloading a document
Follow links.download.src from the attachments list — never construct this URL yourself:
curl -X GET "https://api.pointservices.com/riskinsight-services-ws/resources/v1/findings/workflows/wfpop_0000000000002082611/findings/fndg_0000000000006051384/attachments/attchmnt_0000000000006099213/content" \
-H "Authorization: Bearer your_access_token_here" \
-o paystub-august.pdf
The response is the document’s raw bytes — Content-Type set to the stored media type, Content-Disposition: attachment naming the file. There’s no JSON envelope on this one response, on either success or failure; don’t hand it to a JSON parser.
Notice the download link uses src, not href, and that’s deliberate — every other link on this surface uses href. src (as in <img src>) means “fetch this for content”; href means “navigate to a JSON resource.” It’s your signal, without having to guess from context, that this one link returns bytes rather than JSON.
This endpoint authorizes you on every request the same way every other call here does, and it is not a signed or expiring URL. That means it’s safe to store or hand to another part of your own system, as long as that system can present the same bearer token — but a copy of the URL alone, without a valid token, gets you nothing.
Removing a document
curl -X DELETE "https://api.pointservices.com/riskinsight-services-ws/resources/v1/findings/workflows/wfpop_0000000000002082611/findings/fndg_0000000000006051384/attachments/attchmnt_0000000000006099213" \
-H "Authorization: Bearer your_access_token_here"
This is a soft delete, always — matching the “live only” contract the list above already relies on. Once removed, the attachment stops appearing in the list and stops counting toward hasAttachments, but nothing about this call is reversible from your side.
There’s no in-place edit for an attachment’s content or metadata. To replace one, delete it and upload the replacement as a new attachment — the new one gets its own attachmentId, unrelated to the one you removed.
Permissions
Uploading and removing are gated by one permission, Finding.editStates.attachment — see Reviewing a Finding for how editStates works in general. If that key is absent on a finding, both the upload and the delete calls above are expected to fail with a 403.