Skip to main content

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 returns 204 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 returns 202 Accepted with 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:

  1. 1Access token

    OAuth2 client credentials enabled for support-file upload. See Obtaining tokens.

  2. 2Existing origin event

    At least one origin_event_id from a previously created account/admission.

  3. 3Webhook receiver

    Classification and validation outcomes arrive as webhooks. When support_file_code is omitted, you'll receive two events per upload:

    1. DOCUMENT_CLASSIFICATION_COMPLETED (or DOCUMENT_CLASSIFICATION_FAILED) — within ~5–15 seconds.
    2. 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:

PartTypeRequiredDescription
filebinaryyesThe document. PDF or image (JPEG, PNG).
request_dataJSONyesThe metadata object described below.

request_data fields

FieldTypeRequiredDescription
support_file_codestringnoIf you know the document type, pass it (same behaviour as v1 — synchronous, no DVS). If omitted, RCM asks DVS to classify. Max 64 chars.
eventsarrayyesOne or more events the document supports. Must contain at least one element.
events[].origin_event_idstringyesThe origin event this document supports. Max 64 chars.
events[].agreement_codestringnoAgreement code for the event. Max 64 chars.
events[].charge_codesstring[]noCharge codes to attach the document at charge level. Omit to attach at account level.
authorization_idstringnoAuthorization identifier. Max 256 chars.
authorized_bystringnoWho authorized the upload. Max 128 chars.
support_file_metadataobjectnoFree-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 situationRecommended mode
Your system has a "Document type" dropdown filled by the end userMode 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 boxMode B (omit the code) — let DVS decide.
You're not sure if the user picked the right typeMode 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:

  1. 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.
  2. Fall back to Mode A with an explicit support_file_code if 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 be APPROVED.

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:

  1. Change the URL from /v1/support-files/upload to /v2/support-files/upload.
  2. Keep passing support_file_code inside request_data. The behaviour is identical (skips classification, returns 204 No Content).
  3. Your response handling stays the same — Mode A returns 204 with no body, just like v1.
  4. 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.