Escopo VIO
vio:decodePermite decodificar documentos VIO.
Integre consultas de transporte e leitura de documentos com exemplos prontos, respostas previsíveis e rastreabilidade por requisição.
Crie uma chave em API Keys, mantenha-a somente no servidor e envie-a no header Authorization. A URL base da API é:
https://rododata.com/v1Use variáveis de ambiente ou um gerenciador de segredos no seu backend. A chave completa é exibida apenas no momento da criação.
curl -X POST https://rododata.com/v1/antt/rntrc/vehicle \
-H "Authorization: Bearer $RODODATA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"document":"12345678000199","plate":"ABC1D23"}'Uma resposta bem-sucedida segue este envelope:
{
"success": true,
"data": {
"dt_cadastro": "2025-01-15T00:00:00Z",
"apto_transporte_remunerado": true,
"endereco_municipio": "CURITIBA",
"endereco_uf": "PR",
"mensagem": "",
"rntrc": "01234567",
"situacao": "ATIVO",
"transportador": "EMPRESA EXEMPLO LTDA",
"documento_transportador": "12345678000199",
"veiculo_tipo": "TRATOR",
"placa": "ABC1D23"
},
"processing_time_ms": 842,
"credits_used": 5,
"credits_remaining": 95,
"request_id": "req_..."
}Endpoints comerciais exigem uma API Key ativa e com o escopo correto.
Authorization: Bearer rd_live_xxxxxxxxxvio:decodePermite decodificar documentos VIO.
antt:rntrcPermite consultar RNTRC por documento e placa.
Uma chave sem o escopo necessário recebe 403 FORBIDDEN. Uma chave ausente, inválida ou revogada recebe 401 UNAUTHORIZED.
O limite padrão atual é de 120 requisições por minuto por API Key. A API informa o estado do limite nos headers:
X-RateLimit-Remaining: 117
X-RateLimit-Reset: 1789398120X-RateLimit-Reset é um timestamp Unix. Ao exceder o limite, a API responde 429 RATE_LIMITED.
/v1/vio/decode1 créditoPDF é o formato recomendado. Envie o arquivo original da CNH, CRLV ou outro documento VIO no campo file. A RodoData renderiza o PDF no servidor e procura o QR Code nas primeiras páginas. PNG, JPEG e GIF continuam disponíveis como alternativa.
O processamento considera até as 20 primeiras páginas do PDF e interrompe assim que encontra um QR Code compatível. Para melhor leitura, envie o arquivo original sempre que possível, evitando screenshots ou recompressões.
curl -X POST https://rododata.com/v1/vio/decode \
-H "Authorization: Bearer $RODODATA_API_KEY" \
-F "file=@cnh.pdf;type=application/pdf"import fs from "node:fs";
const form = new FormData();
form.append(
"file",
new Blob([fs.readFileSync("cnh.pdf")], { type: "application/pdf" }),
"cnh.pdf"
);
const response = await fetch("https://rododata.com/v1/vio/decode", {
method: "POST",
headers: {
Authorization: "Bearer " + process.env.RODODATA_API_KEY
},
body: form
});
const data = await response.json();
if (!response.ok) throw new Error(data.error?.message || "Erro na API RodoData");
console.log(data);import os
import requests
with open("cnh.pdf", "rb") as document:
response = requests.post(
"https://rododata.com/v1/vio/decode",
headers={"Authorization": f"Bearer {os.environ['RODODATA_API_KEY']}"},
files={"file": ("cnh.pdf", document, "application/pdf")},
timeout=30,
)
response.raise_for_status()
print(response.json())<?php
$ch = curl_init('https://rododata.com/v1/vio/decode');
$file = new CURLFile('cnh.pdf', 'application/pdf', 'cnh.pdf');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RODODATA_API_KEY'),
],
CURLOPT_POSTFIELDS => ['file' => $file],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($body, true);
if ($status >= 400) {
throw new RuntimeException($data['error']['message'] ?? 'Erro na API RodoData');
}
print_r($data);package main
import (
"bytes"
"encoding/json"
"io"
"mime/multipart"
"net/http"
"os"
"path/filepath"
)
func main() {
var body bytes.Buffer
writer := multipart.NewWriter(&body)
file, _ := os.Open("cnh.pdf")
defer file.Close()
part, _ := writer.CreateFormFile("file", filepath.Base(file.Name()))
_, _ = io.Copy(part, file)
_ = writer.Close()
req, _ := http.NewRequest(http.MethodPost,
"https://rododata.com/v1/vio/decode", &body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("RODODATA_API_KEY"))
req.Header.Set("Content-Type", writer.FormDataContentType())
resp, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
var result any
_ = json.NewDecoder(resp.Body).Decode(&result)
}using System.Net.Http.Headers;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("RODODATA_API_KEY"));
await using var stream = File.OpenRead("cnh.pdf");
using var content = new MultipartFormDataContent();
using var file = new StreamContent(stream);
file.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
content.Add(file, "file", "cnh.pdf");
var response = await client.PostAsync("https://rododata.com/v1/vio/decode", content);
var body = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
Console.WriteLine(body);Se o documento já estiver em imagem, envie PNG, JPEG ou GIF no mesmo campo file. Para integrações que já trabalham com imagem Base64, o JSON abaixo continua aceito.
{
"image_base64": "data:image/png;base64,iVBORw0KGgoAAA..."
}O envelope é estável entre os documentos reconhecidos. Os campos específicos ficam em data.
{
"success": true,
"document": {
"type": "cnh",
"name": "CNH",
"template_id": 83,
"issuer": "SENATRAN",
"recognized": true
},
"validation": {
"signature_checked": true,
"signature_valid": true,
"signature_algorithm": "ECDSA",
"certificate_id": "...",
"qr_created_at": "2026-09-14T12:00:00Z"
},
"data": {
"nome": "NOME EXEMPLO",
"categoria": "B"
},
"meta": {
"qr_version": 6,
"input_encoding": "api-pdf",
"credits_used": 1,
"credits_remaining": 99,
"request_id": "req_..."
}
}Os endpoints de catálogo são públicos e não consomem créditos.
/v1/vio/documentsLista tipos e campos reconhecidos/v1/vio/documents/{templateID}Detalha um template/v1/antt/rntrc/vehicle5 créditosInforme CPF ou CNPJ do transportador e uma placa brasileira com sete caracteres. Pontuação do documento é removida automaticamente; a placa é normalizada para maiúsculas.
{
"document": "12345678000199",
"plate": "ABC1D23"
}const response = await fetch("https://rododata.com/v1/antt/rntrc/vehicle", {
method: "POST",
headers: {
Authorization: "Bearer " + process.env.RODODATA_API_KEY,
"Content-Type": "application/json"
},
body: JSON.stringify({
document: "12345678000199",
plate: "ABC1D23"
})
});
const data = await response.json();
if (!response.ok) throw new Error(data.error?.message || "Erro na API RodoData");
console.log(data);import os
import requests
response = requests.post(
"https://rododata.com/v1/antt/rntrc/vehicle",
headers={
"Authorization": f"Bearer {os.environ['RODODATA_API_KEY']}",
"Content-Type": "application/json",
},
json={"document": "12345678000199", "plate": "ABC1D23"},
timeout=30,
)
response.raise_for_status()
print(response.json())<?php
$ch = curl_init('https://rododata.com/v1/antt/rntrc/vehicle');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RODODATA_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'document' => '12345678000199',
'plate' => 'ABC1D23',
]),
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($body, true);
if ($status >= 400) {
throw new RuntimeException($data['error']['message'] ?? 'Erro na API RodoData');
}
print_r($data);package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
payload, _ := json.Marshal(map[string]string{
"document": "12345678000199",
"plate": "ABC1D23",
})
req, _ := http.NewRequest(http.MethodPost,
"https://rododata.com/v1/antt/rntrc/vehicle",
bytes.NewReader(payload),
)
req.Header.Set("Authorization", "Bearer "+os.Getenv("RODODATA_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
var result any
_ = json.NewDecoder(resp.Body).Decode(&result)
fmt.Printf("status=%d result=%#v\n", resp.StatusCode, result)
}using System.Net.Http.Headers;
using System.Net.Http.Json;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("RODODATA_API_KEY"));
var response = await client.PostAsJsonAsync(
"https://rododata.com/v1/antt/rntrc/vehicle",
new { document = "12345678000199", plate = "ABC1D23" }
);
var body = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
Console.WriteLine(body);Toda chamada comercial recebe um identificador próprio. Guarde o request_id ao registrar erros no seu sistema.
X-Request-ID: req_...
X-Credits-Remaining: 95
X-RateLimit-Remaining: 117
X-RateLimit-Reset: 1789398120X-Credits-Remaining aparece em consultas comerciais concluídas. O mesmo identificador de requisição também é retornado no JSON.
Erros usam sempre o mesmo envelope:
{
"success": false,
"error": {
"code": "INVALID_REQUEST",
"message": "informe CPF/CNPJ e placa válidos"
},
"request_id": "req_..."
}400INVALID_REQUESTJSON, PDF, imagem ou parâmetros inválidos.401UNAUTHORIZEDAPI Key ausente, inválida ou revogada.402INSUFFICIENT_CREDITSSaldo insuficiente para reservar a consulta.403FORBIDDENA chave não possui o escopo solicitado.404DOCUMENT_NOT_FOUNDTemplate VIO não encontrado.422DOCUMENT_NOT_PROCESSEDQR Code não pôde ser processado.429RATE_LIMITEDLimite temporário excedido.500INTERNAL_ERRORFalha interna da RodoData.502UPSTREAM_ERRORFonte externa não concluiu a consulta.503SERVICE_UNAVAILABLEServiço temporariamente indisponível, inclusive o processamento de PDF quando o renderizador não estiver disponível.crédito por consulta concluída.
créditos por consulta concluída.
O saldo é reservado antes do processamento. Se a consulta falhar durante o processamento interno ou na fonte externa, a RodoData estorna os créditos da requisição. Erros de validação, autenticação, escopo e rate limit acontecem antes da cobrança.
rd_live_... em JavaScript enviado ao navegador, aplicativos distribuídos ou repositórios.429, 502 e 503. Não repita automaticamente erros 400, 401, 402, 403 ou 422.request_id junto do erro. Ele é a principal referência para diagnóstico e suporte.Envie o request_id, horário aproximado e endpoint utilizado. Não envie a sua API Key.