Upload a support file (v2 — optional auto-classification)
The v2 upload endpoint unifies the two real-world cases under one contract:
- You know the document type → pass
support_file_code. v2 behaves like v1: it skips DVS classification and processes the file synchronously against the provider's support-document catalog. The endpoint returns204 No Content. - You don't know the document type → omit
support_file_code. RCM persists the file and asks DVS to classify it asynchronously, then runs validation. The endpoint returns202 Acceptedwith a document id you can correlate with the webhooks.
If you only have the "you know the type" case, you can keep using v1 — it's identical for that flow. v2 exists for systems pulling documents from generic sources (email attachments, scanner inboxes, drag-and-drop UIs) where the type can't be reliably determined client-side.
Prerequisites
Same as v1:
- 1Access token
OAuth2 client credentials enabled for support-file upload. See Obtaining tokens.
- 2Existing origin event
At least one
origin_event_idfrom a previously created account/admission. - 3Webhook receiver
Classification and validation outcomes arrive as webhooks. When
support_file_codeis omitted, you'll receive two events per upload:DOCUMENT_CLASSIFICATION_COMPLETED(orDOCUMENT_CLASSIFICATION_FAILED) — within ~5–15 seconds.- If classification completed → a
DOCUMENT_VALIDATION_*event follows ~10–30 seconds later.
See Webhook events → Classification for the full payloads.
Endpoint
POST /v2/support-files/upload
Content-Type: multipart/form-data
Authorization: Bearer <token>
The request is multipart/form-data with two parts:
| Part | Type | Required | Description |
|---|---|---|---|
file | binary | yes | The document. PDF or image (JPEG, PNG). |
request_data | JSON | yes | The metadata object described below. |
request_data fields
| Field | Type | Required | Description |
|---|---|---|---|
support_file_code | string | no | If you know the document type, pass it (same behaviour as v1 — synchronous, no DVS). If omitted, RCM asks DVS to classify. Max 64 chars. |
events | array | yes | One or more events the document supports. Must contain at least one element. |
events[].origin_event_id | string | yes | The origin event this document supports. Max 64 chars. |
events[].agreement_code | string | no | Agreement code for the event. Max 64 chars. |
events[].charge_codes | string[] | no | Charge codes to attach the document at charge level. Omit to attach at account level. |
authorization_id | string | no | Authorization identifier. Max 256 chars. |
authorized_by | string | no | Who authorized the upload. Max 128 chars. |
support_file_metadata | object | no | Free-form key-value pairs. Stored alongside the file, returned in webhook events. |
Two upload modes
Mode A — support_file_code provided
Identical behaviour to v1: RCM skips classification and processes the file synchronously against the provider's support-document catalog. Use this mode when migrating an existing v1 integration to v2 without changing your business logic.
curl -X POST https://sandbox.osigu.com/rcm/v2/support-files/upload \
-H "Authorization: Bearer $TOKEN" \
-F "file=@./guia.pdf;type=application/pdf" \
-F 'request_data={"support_file_code":"TISS_GUIDE","events":[{"origin_event_id":"evt-123","agreement_code":"AGR-001","charge_codes":["QS-0001"]}]};type=application/json'
Response: 204 No Content (empty body).
Because the file is processed synchronously, there is no document id to return — the outcome is applied immediately, exactly as in v1. If the support_file_code does not exist or is disabled for your provider, the endpoint returns 404 Not Found with error code 055-0300-0020 (error.support-document.not-found).
Mode B — support_file_code omitted
RCM enters the auto-classify flow: it persists the file and submits it to DVS asynchronously.
curl -X POST https://sandbox.osigu.com/rcm/v2/support-files/upload \
-H "Authorization: Bearer $TOKEN" \
-F "file=@./documento_desconocido.pdf;type=application/pdf" \
-F 'request_data={"events":[{"origin_event_id":"evt-123"}]};type=application/json'
Response (202 Accepted):
{
"document_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "RECEIVED"
}
Use document_id to correlate the upload with the classification and validation webhooks that follow. First you'll receive a DOCUMENT_CLASSIFICATION_* event. If it's DOCUMENT_CLASSIFICATION_COMPLETED, RCM persists the detected support_file_code on the support file record AND runs validation; a DOCUMENT_VALIDATION_* event arrives afterwards. If it's DOCUMENT_CLASSIFICATION_FAILED, the file goes to UNCLASSIFIED state and no validation event will follow.
Choosing between modes
| Your situation | Recommended mode |
|---|---|
| Your system has a "Document type" dropdown filled by the end user | Mode A (pass the code) — DVS doesn't need to classify what the user already told you. |
| Your system receives documents from email or a generic upload box | Mode B (omit the code) — let DVS decide. |
| You're not sure if the user picked the right type | Mode A is still safer: DVS validates based on the code you passed. If it rejects with field-mismatch errors, the user may have picked the wrong type. |
| You're building a fully automated pipeline (PMS → RCM, no human) | Depends. If the source signals the type unambiguously, Mode A. Otherwise Mode B + fallback to manual review on DOCUMENT_CLASSIFICATION_FAILED. |
Node.js example (Mode B)
import fs from 'node:fs';
import FormData from 'form-data';
import fetch from 'node-fetch';
async function autoClassifyAndValidate({token, filePath, originEventId, chargeCodes}) {
const form = new FormData();
form.append('file', fs.createReadStream(filePath), {contentType: 'application/pdf'});
// NB: support_file_code intentionally omitted — RCM will ask DVS to classify
const requestData = {
events: [{origin_event_id: originEventId, charge_codes: chargeCodes ?? []}],
};
form.append('request_data', JSON.stringify(requestData), {contentType: 'application/json'});
const res = await fetch('https://sandbox.osigu.com/rcm/v2/support-files/upload', {
method: 'POST',
headers: {Authorization: `Bearer ${token}`},
body: form,
});
if (res.status !== 202) {
throw new Error(`Upload failed: ${res.status} ${await res.text()}`);
}
const {document_id, status} = await res.json();
console.log(`Uploaded document=${document_id} status=${status}`);
// Now wait for DOCUMENT_CLASSIFICATION_* and DOCUMENT_VALIDATION_* webhooks.
return document_id;
}
Handling the two-event flow in Mode B
Your receiver needs to handle both classification and validation events for the same document_id. A simple state machine:
state(document_id) = AWAITING_CLASSIFICATION
→ on DOCUMENT_CLASSIFICATION_COMPLETED → set support_file_code, AWAITING_VALIDATION
→ on DOCUMENT_CLASSIFICATION_FAILED → UNCLASSIFIED, surface to operator
state(document_id) = AWAITING_VALIDATION
→ on DOCUMENT_VALIDATION_COMPLETED → APPROVED
→ on DOCUMENT_VALIDATION_REJECTED → REJECTED, surface errors
For idempotency: store event_id as a primary key in a processed_events table before applying the state transition. If the same event_id arrives twice, the insert fails and you skip processing.
What if I want auto-classification but RCM rejects the file with LOW_CONFIDENCE?
Two paths forward:
- Re-upload a cleaner copy of the same document — re-scan at higher quality, or pull the PDF directly from the source system instead of via an email forward.
- Fall back to Mode A with an explicit
support_file_codeif you and the end user actually know what the document is. DVS will skip classification and go straight to validation; if the rules match, the file will beAPPROVED.
There's no automatic re-classification in RCM — once a file is UNCLASSIFIED, you have to act on it explicitly.
Migration from v1
If you're switching from v1 to v2 without changing your business logic:
- Change the URL from
/v1/support-files/uploadto/v2/support-files/upload. - Keep passing
support_file_codeinsiderequest_data. The behaviour is identical (skips classification, returns204 No Content). - Your response handling stays the same — Mode A returns
204with no body, just like v1. - Your webhook handler stays the same — Mode A on v2 emits the same
validation.*events as v1.
No webhook subscription changes needed; the same subscription works for both v1 and v2 uploads.