curl --request POST \
--url https://api-sandbox.rinne.com.br/core/v1/merchants/{merchantId}/onboarding-documents/{id}/complete \
--header 'x-api-key: <api-key>'import requests
url = "https://api-sandbox.rinne.com.br/core/v1/merchants/{merchantId}/onboarding-documents/{id}/complete"
headers = {"x-api-key": "<api-key>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {'x-api-key': '<api-key>'}};
fetch('https://api-sandbox.rinne.com.br/core/v1/merchants/{merchantId}/onboarding-documents/{id}/complete', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-sandbox.rinne.com.br/core/v1/merchants/{merchantId}/onboarding-documents/{id}/complete",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api-sandbox.rinne.com.br/core/v1/merchants/{merchantId}/onboarding-documents/{id}/complete"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api-sandbox.rinne.com.br/core/v1/merchants/{merchantId}/onboarding-documents/{id}/complete")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-sandbox.rinne.com.br/core/v1/merchants/{merchantId}/onboarding-documents/{id}/complete")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"id": "9c1e7b3a-2d4f-4a6b-8c0d-5e7f9a1b3c2d",
"company_id": "c0a8012e-4d3b-4a6e-8f1b-1a2b3c4d5e6f",
"subject_document_number": "81146431023",
"type": "PROOF_OF_ADDRESS",
"status": "NOT_VALIDATED",
"source": "UPLOAD",
"requirement_id": null,
"file_name": "address.pdf",
"content_type": "application/pdf",
"file_size_bytes": 125430,
"upload_url_expires_at": null,
"rejections": [
{
"provider": "CELCOIN",
"affiliation_id": "aff_123456789",
"reason_code": "DOCUMENT_UNREADABLE",
"message": null,
"rejected_at": "2026-10-09T12:00:00.000Z"
}
],
"superseded_by_id": null,
"screening": null,
"screening_note": null,
"created_at": "2026-10-09T12:00:00.000Z",
"updated_at": "2026-10-09T12:00:00.000Z"
}{
"id": "9c1e7b3a-2d4f-4a6b-8c0d-5e7f9a1b3c2d",
"company_id": "c0a8012e-4d3b-4a6e-8f1b-1a2b3c4d5e6f",
"subject_document_number": "81146431023",
"type": "PROOF_OF_ADDRESS",
"status": "NOT_VALIDATED",
"source": "UPLOAD",
"requirement_id": null,
"file_name": "address.pdf",
"content_type": "application/pdf",
"file_size_bytes": 125430,
"upload_url_expires_at": null,
"rejections": [
{
"provider": "CELCOIN",
"affiliation_id": "aff_123456789",
"reason_code": "DOCUMENT_UNREADABLE",
"message": null,
"rejected_at": "2026-10-09T12:00:00.000Z"
}
],
"superseded_by_id": null,
"screening": null,
"screening_note": null,
"created_at": "2026-10-09T12:00:00.000Z",
"updated_at": "2026-10-09T12:00:00.000Z"
}{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation error",
"status": 400,
"details": {
"issues": [
{
"field": "email",
"type": "REQUIRED",
"message": "Field 'email' is required",
"value": "invalid_value",
"constraints": {
"min": 18,
"max": 120
}
}
]
},
"path": "/companies",
"timestamp": "2023-12-01T10:00:00.000Z",
"requestId": "req_123456789"
}
}{
"error": {
"code": "AUTHENTICATION_ERROR",
"message": "Authentication required to access this resource",
"status": 401,
"details": {
"reason": "Invalid API key"
},
"path": "/companies/me",
"timestamp": "2023-12-01T10:00:00.000Z",
"requestId": "req_123456789"
}
}{
"error": {
"code": "AUTHORIZATION_ERROR",
"message": "You need 'admin' permissions to access this resource",
"status": 403,
"path": "/companies",
"timestamp": "2023-12-01T10:00:00.000Z",
"requestId": "req_123456789"
}
}{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "Company with ID '123' not found",
"status": 404,
"path": "/companies/me",
"timestamp": "2023-12-01T10:00:00.000Z",
"requestId": "req_123456789"
}
}{
"error": {
"code": "CONFLICT_ERROR",
"message": "No file was uploaded for this document yet",
"status": 409,
"details": {
"onboarding_document_id": "9c1e7b3a-2d4f-4a6b-8c0d-5e7f9a1b3c2d"
}
}
}{
"error": {
"code": "GONE_ERROR",
"message": "The upload window of this document expired; open a new one",
"status": 410,
"details": {
"onboarding_document_id": "9c1e7b3a-2d4f-4a6b-8c0d-5e7f9a1b3c2d"
},
"path": "/v1/onboarding-documents/9c1e7b3a-2d4f-4a6b-8c0d-5e7f9a1b3c2d/complete",
"timestamp": "2026-10-09T12:20:00.000Z",
"requestId": "req_123456789"
}
}{
"error": {
"code": "INTERNAL_SERVER_ERROR",
"message": "An unexpected error occurred",
"status": 500,
"path": "/companies",
"timestamp": "2023-12-01T10:00:00.000Z",
"requestId": "req_123456789"
}
}Complete an onboarding document upload
Requires the merchant.onboarding-document.create permission.
Closes the upload opened by POST on the collection: reads the file behind the signed URL, checks it is a
PDF, PNG or JPEG of at most 10 MB whose bytes match the declared content_type (a file that fails answers
400 and is deleted; PUT a corrected file to the same URL until it expires, then open a new upload), records it, and moves the document to NOT_VALIDATED. The
previous current document of the same subject and type becomes SUPERSEDED; both changes are reported by
onboarding-document.status-changed. Validation by the provider and the status it leads to come later,
through the affiliation that sends the document.
A file already held as a current document of the same subject and type (the same bytes) answers 201
with that existing document, and the one just opened is closed as SUPERSEDED by it. A document already
completed answers 200 with it as it is.
curl --request POST \
--url https://api-sandbox.rinne.com.br/core/v1/merchants/{merchantId}/onboarding-documents/{id}/complete \
--header 'x-api-key: <api-key>'import requests
url = "https://api-sandbox.rinne.com.br/core/v1/merchants/{merchantId}/onboarding-documents/{id}/complete"
headers = {"x-api-key": "<api-key>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {'x-api-key': '<api-key>'}};
fetch('https://api-sandbox.rinne.com.br/core/v1/merchants/{merchantId}/onboarding-documents/{id}/complete', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-sandbox.rinne.com.br/core/v1/merchants/{merchantId}/onboarding-documents/{id}/complete",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api-sandbox.rinne.com.br/core/v1/merchants/{merchantId}/onboarding-documents/{id}/complete"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api-sandbox.rinne.com.br/core/v1/merchants/{merchantId}/onboarding-documents/{id}/complete")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-sandbox.rinne.com.br/core/v1/merchants/{merchantId}/onboarding-documents/{id}/complete")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"id": "9c1e7b3a-2d4f-4a6b-8c0d-5e7f9a1b3c2d",
"company_id": "c0a8012e-4d3b-4a6e-8f1b-1a2b3c4d5e6f",
"subject_document_number": "81146431023",
"type": "PROOF_OF_ADDRESS",
"status": "NOT_VALIDATED",
"source": "UPLOAD",
"requirement_id": null,
"file_name": "address.pdf",
"content_type": "application/pdf",
"file_size_bytes": 125430,
"upload_url_expires_at": null,
"rejections": [
{
"provider": "CELCOIN",
"affiliation_id": "aff_123456789",
"reason_code": "DOCUMENT_UNREADABLE",
"message": null,
"rejected_at": "2026-10-09T12:00:00.000Z"
}
],
"superseded_by_id": null,
"screening": null,
"screening_note": null,
"created_at": "2026-10-09T12:00:00.000Z",
"updated_at": "2026-10-09T12:00:00.000Z"
}{
"id": "9c1e7b3a-2d4f-4a6b-8c0d-5e7f9a1b3c2d",
"company_id": "c0a8012e-4d3b-4a6e-8f1b-1a2b3c4d5e6f",
"subject_document_number": "81146431023",
"type": "PROOF_OF_ADDRESS",
"status": "NOT_VALIDATED",
"source": "UPLOAD",
"requirement_id": null,
"file_name": "address.pdf",
"content_type": "application/pdf",
"file_size_bytes": 125430,
"upload_url_expires_at": null,
"rejections": [
{
"provider": "CELCOIN",
"affiliation_id": "aff_123456789",
"reason_code": "DOCUMENT_UNREADABLE",
"message": null,
"rejected_at": "2026-10-09T12:00:00.000Z"
}
],
"superseded_by_id": null,
"screening": null,
"screening_note": null,
"created_at": "2026-10-09T12:00:00.000Z",
"updated_at": "2026-10-09T12:00:00.000Z"
}{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation error",
"status": 400,
"details": {
"issues": [
{
"field": "email",
"type": "REQUIRED",
"message": "Field 'email' is required",
"value": "invalid_value",
"constraints": {
"min": 18,
"max": 120
}
}
]
},
"path": "/companies",
"timestamp": "2023-12-01T10:00:00.000Z",
"requestId": "req_123456789"
}
}{
"error": {
"code": "AUTHENTICATION_ERROR",
"message": "Authentication required to access this resource",
"status": 401,
"details": {
"reason": "Invalid API key"
},
"path": "/companies/me",
"timestamp": "2023-12-01T10:00:00.000Z",
"requestId": "req_123456789"
}
}{
"error": {
"code": "AUTHORIZATION_ERROR",
"message": "You need 'admin' permissions to access this resource",
"status": 403,
"path": "/companies",
"timestamp": "2023-12-01T10:00:00.000Z",
"requestId": "req_123456789"
}
}{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "Company with ID '123' not found",
"status": 404,
"path": "/companies/me",
"timestamp": "2023-12-01T10:00:00.000Z",
"requestId": "req_123456789"
}
}{
"error": {
"code": "CONFLICT_ERROR",
"message": "No file was uploaded for this document yet",
"status": 409,
"details": {
"onboarding_document_id": "9c1e7b3a-2d4f-4a6b-8c0d-5e7f9a1b3c2d"
}
}
}{
"error": {
"code": "GONE_ERROR",
"message": "The upload window of this document expired; open a new one",
"status": 410,
"details": {
"onboarding_document_id": "9c1e7b3a-2d4f-4a6b-8c0d-5e7f9a1b3c2d"
},
"path": "/v1/onboarding-documents/9c1e7b3a-2d4f-4a6b-8c0d-5e7f9a1b3c2d/complete",
"timestamp": "2026-10-09T12:20:00.000Z",
"requestId": "req_123456789"
}
}{
"error": {
"code": "INTERNAL_SERVER_ERROR",
"message": "An unexpected error occurred",
"status": 500,
"path": "/companies",
"timestamp": "2023-12-01T10:00:00.000Z",
"requestId": "req_123456789"
}
}Authorizations
Company API key for authentication
Path Parameters
The merchant ID
The onboarding document ID
Response
The document was already completed; returned as it is
A document a company holds for a subject, as the list, read and complete responses carry it
"9c1e7b3a-2d4f-4a6b-8c0d-5e7f9a1b3c2d"
The company the document was presented for (the organization itself or one of its merchants)
"c0a8012e-4d3b-4a6e-8f1b-1a2b3c4d5e6f"
Whom the document is about, digits only (a CPF or a CNPJ)
"81146431023"
RNM_* and ID_DOCUMENT_* only arrive from a provider's capture; SELFIE from a capture or an upload
CNH_FRONT, CNH_BACK, CNH_DIGITAL, RG_FRONT, RG_BACK, RNE_FRONT, RNE_BACK, RNM_FRONT, RNM_BACK, ID_DOCUMENT_FRONT, ID_DOCUMENT_BACK, SELFIE, ARTICLES_OF_INCORPORATION, POWER_OF_ATTORNEY, PROOF_OF_ADDRESS, PROOF_OF_INCOME, FINANCIAL_STATEMENT, OTHER "PROOF_OF_ADDRESS"
PENDING_UPLOAD until complete; NOT_VALIDATED once the file is recorded and until a provider judges it;
VALIDATED when a provider accepted it; REJECTED when every provider that saw it refused it (see rejections);
SUPERSEDED when a newer document of the same subject and type replaced it, when complete found its bytes
already stored in another document (superseded_by_id), or when Rinne closed an upload whose URL expired with
nothing received (superseded_by_id null).
PENDING_UPLOAD, NOT_VALIDATED, VALIDATED, REJECTED, SUPERSEDED "NOT_VALIDATED"
UPLOAD by the customer; PROVIDER from a provider's capture; SHARED a reference to a document another organization validated for the same subject
UPLOAD, PROVIDER, SHARED "UPLOAD"
The EVIDENCE_PACKAGE requirement the document is attached to; null for every other document
null
The name given at upload, or the name the provider's capture produced; null on a SHARED document
"address.pdf"
The file's MIME type; null until the upload completes and on a SHARED document
"application/pdf"
null until the upload completes and on a SHARED document
125430
When the signed upload URL stops accepting the file; null once uploaded
null
In the list, read and complete responses, the provider refusals of these bytes, newest first, from every document of the organization that holds the same file for the same subject, this one included. The entity of a webhook carries the refusals recorded on this document only
Show child attributes
Show child attributes
The document that replaced this one, or that already held its bytes, when SUPERSEDED
null
Rinne's own check of the file before any provider reads it: PENDING until Rinne looks at it,
then PASSED or FAILED. A FAILED document satisfies no requirement and its requirement reads
REJECTED, with screening_note saying why; upload a new one. Always null while Rinne does not
screen documents.
PENDING, PASSED, FAILED, null null
The screener's note on a FAILED, saying why the document did not pass; null on any other verdict, and always null while Rinne does not screen documents
null
"2026-10-09T12:00:00.000Z"
"2026-10-09T12:00:00.000Z"

