Documentação

API RodoData v1

Integre consultas de transporte e leitura de documentos com exemplos prontos, respostas previsíveis e rastreabilidade por requisição.

Comece aqui

Primeira chamada em poucos minutos

Crie uma chave em API Keys, mantenha-a somente no servidor e envie-a no header Authorization. A URL base da API é:

Base URL
https://rododata.com/v1
Não coloque a API Key no navegador.

Use variáveis de ambiente ou um gerenciador de segredos no seu backend. A chave completa é exibida apenas no momento da criação.

Exemplo rápido — ANTT / RNTRC

cURL
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:

HTTP 200
{
  "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_..."
}
Segurança

Autenticação Bearer

Endpoints comerciais exigem uma API Key ativa e com o escopo correto.

Header
Authorization: Bearer rd_live_xxxxxxxxx

Escopo VIO

vio:decode

Permite decodificar documentos VIO.

Escopo ANTT

antt:rntrc

Permite 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.

Proteção

Rate limit

O limite padrão atual é de 120 requisições por minuto por API Key. A API informa o estado do limite nos headers:

Headers
X-RateLimit-Remaining: 117
X-RateLimit-Reset: 1789398120

X-RateLimit-Reset é um timestamp Unix. Ao exceder o limite, a API responde 429 RATE_LIMITED.

Documentos

VIO API

POST/v1/vio/decode1 crédito

PDF é 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.

PDF em primeiro lugar.

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.

PDF — formato recomendado

cURL
curl -X POST https://rododata.com/v1/vio/decode \
  -H "Authorization: Bearer $RODODATA_API_KEY" \
  -F "file=@cnh.pdf;type=application/pdf"
Node.js
Node.js
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);
Python
Python
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
PHP
<?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);
Go
Go
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)
}
C#
C#
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);

Imagem ou Base64

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.

JSON
{
  "image_base64": "data:image/png;base64,iVBORw0KGgoAAA..."
}

Resposta normalizada

O envelope é estável entre os documentos reconhecidos. Os campos específicos ficam em data.

HTTP 200
{
  "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_..."
  }
}

Catálogo de documentos

Os endpoints de catálogo são públicos e não consomem créditos.

GET/v1/vio/documentsLista tipos e campos reconhecidos
GET/v1/vio/documents/{templateID}Detalha um template
Transporte

ANTT / RNTRC por veículo

POST/v1/antt/rntrc/vehicle5 créditos

Informe CPF ou CNPJ do transportador e uma placa brasileira com sete caracteres. Pontuação do documento é removida automaticamente; a placa é normalizada para maiúsculas.

Body JSON
{
  "document": "12345678000199",
  "plate": "ABC1D23"
}

Exemplos por linguagem

Node.js
Node.js
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);
Python
Python
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
PHP
<?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);
Go
Go
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)
}
C#
C#
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);
Contrato

Headers e rastreabilidade

Toda chamada comercial recebe um identificador próprio. Guarde o request_id ao registrar erros no seu sistema.

Headers úteis
X-Request-ID: req_...
X-Credits-Remaining: 95
X-RateLimit-Remaining: 117
X-RateLimit-Reset: 1789398120

X-Credits-Remaining aparece em consultas comerciais concluídas. O mesmo identificador de requisição também é retornado no JSON.

Falhas

Erros previsíveis

Erros usam sempre o mesmo envelope:

Exemplo
{
  "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.
Cobrança

Como os créditos são consumidos

VIO

1

crédito por consulta concluída.

ANTT / RNTRC

5

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.

Boas práticas

Integração em produção

Segredo no backendNunca exponha rd_live_... em JavaScript enviado ao navegador, aplicativos distribuídos ou repositórios.
Timeout explícitoConfigure timeout HTTP no cliente. Consultas que dependem de fontes externas ou renderização de PDF podem demorar mais que chamadas puramente locais.
Retry seletivoConsidere retry com backoff para falhas de rede, 429, 502 e 503. Não repita automaticamente erros 400, 401, 402, 403 ou 422.
Request IDRegistre o request_id junto do erro. Ele é a principal referência para diagnóstico e suporte.
Não registre dados sensíveisEvite armazenar API Keys, PDFs, imagens, QR Codes, documentos completos ou respostas pessoais desnecessariamente.
Precisa de suporte?

Envie o request_id, horário aproximado e endpoint utilizado. Não envie a sua API Key.