Esta API permite que você venda certificados de Normas Regulamentadoras (NR) dentro da sua própria plataforma. Você exibe as NRs com o seu preço, recebe o pedido do seu cliente e nos repassa por uma chamada. A partir daí, todo o processo acontece na plataforma REGULASEG — pagamento, treinamento, assinatura e emissão — e você é notificado a cada etapa até receber o certificado pronto.
1. Como funciona
- Você mostra o catálogo.
GET /cursosdevolve as NRs disponíveis com o preço negociado com você. - Seu cliente compra na sua plataforma, escolhendo as pessoas e as NRs.
- Você repassa o pedido.
POST /pedidoscom quem vai receber certificado e quais certificados. A resposta traz o link de pagamento. - Seu cliente completa a jornada na REGULASEG. Ele abre o link, escolhe como pagar e paga. Depois recebe o acesso por e-mail, aceita o termo de conclusão do treinamento e assina o certificado.
- Você é avisado a cada etapa por webhook, até o
certificate.signedcom os dados do certificado e o link de validação.
você REGULASEG
──── ─────────
GET /cursos ──────────────► catálogo com o seu preço
POST /pedidos ──────────────► cria o pedido
◄────────────── linkPagamento
│
(seu cliente abre o link e paga) │
◄────────────── webhook order.paid
◄────────────── webhook certificate.issued
◄────────────── webhook term.accepted
◄────────────── webhook certificate.signed ← certificado pronto
O que você não precisa fazer: processar pagamento, hospedar treinamento, coletar assinatura ou guardar PDF. Nada disso passa pelo seu sistema.
2. Autenticação
Toda requisição leva a chave no cabeçalho:
Authorization: Bearer rsk_openstaff_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
A chave carrega o seu código de parceiro (a parte do meio, pública) e o segredo. Ela é entregue uma única vez, por canal seguro, e deve ficar num gerenciador de segredos — nunca em repositório, log ou código de front-end.
Se a chave vazar, avise em fale com a gente: revogamos na hora e conseguimos listar tudo o que foi criado com ela.
3. Convenções
| Tema | Regra |
|---|---|
| Base | https://app.regulaseg.com.br/api/v1/partner |
| Formato | JSON. Envie Content-Type: application/json |
| Valores | Sempre em centavos, inteiros. 5990 = R$ 59,90 |
| Datas | ISO 8601 em UTC. Datas sem hora em YYYY-MM-DD |
| Documentos | CPF e CNPJ só dígitos, sem pontuação |
| Telefone | Celular brasileiro com DDD, só dígitos: 15991234567 |
| Rastreio | Toda resposta traz X-Request-Id. Cite ao abrir chamado |
Erros seguem sempre a mesma forma, e vêm todos de uma vez:
{
"erro": "DADOS_INVALIDOS",
"mensagem": "3 de 200 trabalhadores com problema. Nada foi criado.",
"detalhes": [
{ "ref": "func-882", "indice": 3, "campo": "telefone", "codigo": "DADOS_INVALIDOS",
"mensagem": "Informe um celular com WhatsApp válido: DDD + 9 dígitos (ex.: 11 91234-5678)." },
{ "ref": "func-907", "indice": 28, "campo": "cpf", "codigo": "DADOS_INVALIDOS",
"mensagem": "CPF inválido." },
{ "ref": "func-941", "indice": 62, "campo": "email", "codigo": "PESSOA_DUPLICADA",
"mensagem": "E-mail repetido: já está em func-903. Cada pessoa precisa de um e-mail próprio." }
],
"requestId": "req_01J8ZQ..."
}
Num lote de 200 pessoas você recebe a lista completa do que precisa corrigir numa única
chamada — não um erro por tentativa. O erro do topo é o de maior gravidade; cada item de
detalhes carrega o seu próprio codigo. O indice é a posição em pessoas[], útil quando o
mesmo ref aparece repetido.
Quando há erro, nada é criado. Nem pedido, nem contas, nem cobrança. Corrija e reenvie com o
mesmo externalRef.
Idempotência. Todo pedido exige um externalRef — o identificador do pedido no seu sistema.
- Em caso de timeout ou falha de rede, a ação segura é repetir a mesma requisição. Nunca gere um
externalRefnovo para uma retentativa: seria uma segunda venda, e seu cliente pagaria duas vezes. - Se o pedido já foi criado, respondemos 200 com o pedido original e o cabeçalho
Idempotent-Replay: true. - Atenção: o replay devolve o pedido como foi criado e ignora o corpo novo. Para corrigir algo de um pedido que já existe, fale com a gente — não adianta reenviar com o conteúdo alterado.
4. Endpoints
4.1 GET /cursos
Devolve as NRs que você vende, com o seu preço.
{
"cursos": [
{
"codigo": "NR35",
"titulo": "NR-35 — Trabalho em Altura",
"cargaHoraria": 8,
"validadeMeses": 24,
"exigePratico": true,
"precoCentavos": 4500
},
{
"codigo": "NR10",
"titulo": "NR-10 — Segurança em Instalações e Serviços com Eletricidade",
"cargaHoraria": 40,
"validadeMeses": 24,
"exigePratico": false,
"precoCentavos": 4500
}
]
}
Não fixe códigos nem preços no seu código. O catálogo muda quando uma norma é atualizada ou o preço é renegociado. Consulte este endpoint e guarde em cache por no máximo 5 minutos.
exigePratico: true significa que aquela NR exige treinamento prático presencial — o
trabalhador declara que o realizou antes de assinar o certificado. Hoje é o caso da NR-33 e da
NR-35.
4.2 POST /pedidos
Cria o pedido. Aceita uma pessoa ou muitas, e uma NR ou várias por pessoa.
{
"externalRef": "PO-2026-1234",
// Quem paga. A cobrança é emitida no nome desta empresa.
"comprador": {
"razaoSocial": "Construtora Alfa Ltda",
"cnpj": "12345678000199",
"email": "[email protected]",
"telefone": "15991234567"
},
// Vai impresso no certificado quando não vier na pessoa.
"empresa": {
"razaoSocial": "Construtora Alfa Ltda",
"cnpj": "12345678000199",
"localTreinamento": "Sorocaba/SP"
},
// Opcional. Sem isso, calculamos pela carga horária em dias úteis.
"periodoTreinamento": { "inicio": "2026-09-14", "fim": "2026-09-18" },
// NRs padrão do pedido — cada pessoa pode ter as suas.
"cursos": ["NR10", "NR35"],
"pessoas": [
{
"ref": "func-882",
"nome": "João Carlos da Silva",
"cpf": "12345678909",
"email": "[email protected]",
"telefone": "15991234567",
"cargo": "Eletricista",
"cidade": "Sorocaba",
"uf": "SP",
"cursos": ["NR10"]
},
{
"ref": "func-883",
"nome": "Maria de Souza Lima",
"cpf": "98765432100",
"email": "[email protected]",
"telefone": "15998765432",
"cargo": "Montadora"
// sem "cursos" → recebe as duas NRs padrão do pedido
}
]
}
Campos
comprador — quem paga.
| Campo | Obrigatório | Observação |
|---|---|---|
razaoSocial |
sim | Razão social, ou nome completo se for pessoa física |
cnpj |
sim | 14 dígitos. CPF de 11 dígitos é aceito para comprador pessoa física |
email |
sim | Vira o acesso da empresa para acompanhar os certificados |
telefone |
sim | Celular com DDD |
pessoas[] — os trabalhadores. É daqui que sai o certificado.
| Campo | Obrigatório | Onde aparece |
|---|---|---|
ref |
sim | Seu identificador do trabalhador. Devolvemos em toda resposta e webhook |
nome |
sim | Impresso no certificado (nome completo, 2+ palavras) |
cpf |
sim | Impresso no certificado (11 dígitos, validado) |
email |
sim | Acesso do trabalhador e envio do link de assinatura |
telefone |
sim | Link de assinatura por WhatsApp (DDD + 9 dígitos) |
contratante |
não | Impresso no certificado como empresa contratante |
cnpjContratante |
não | Impresso no certificado, ao lado da contratante |
cidade |
não | Vira o "local do treinamento" quando a pessoa tem contratante próprio |
cargo |
não | Fica no cadastro. Não é impresso no certificado |
rg |
não | Fica no cadastro. Não é impresso no certificado |
tratamento |
não | SR ou SRA. Fica no cadastro. Não é impresso no certificado |
uf |
não | Fica no cadastro |
cursos |
não | Sobrescreve o cursos do pedido |
O telefone precisa ser um celular real. O link de assinatura vai por WhatsApp. Número fixo ou fictício impede a conclusão da emissão — é a causa número um de pedido travado.
Cada trabalhador pode ter uma empregadora diferente no mesmo pedido: basta informar
contratanteecnpjContratantena pessoa. Quando você informacontratantesemcnpjContratante, o certificado sai com o nome dessa empresa e o CNPJ do pedido — mande sempre os dois juntos.
O que sai impresso no certificado, e só isso: nome, CPF, empresa contratante, CNPJ, local do treinamento, e os dados do curso (título, carga horária, base legal, datas). Os demais campos alimentam o cadastro, aparecem no painel do seu cliente e nos relatórios — mas não no documento.
Limites: 200 pessoas e 500 itens (pessoa × NR) por pedido. A conta é multiplicativa — 200 pessoas × 3 NRs = 600 itens, acima do limite.
Não envie biometria, foto, documento digitalizado, dados de catraca ou atestado médico. Nada disso é usado na emissão.
Resposta 201
{
"pedidoId": "cmg7x2k9a0001abcd",
"externalRef": "PO-2026-1234",
"status": "aguardando_pagamento",
"totalCentavos": 13500,
"linkPagamento": "https://app.regulaseg.com.br/checkout/cmg7x2k9a0001abcd",
"pessoas": [
{ "ref": "func-882", "pessoaId": "cmg7x9a1b0002defg",
"nome": "João Carlos da Silva", "cpf": "12345678909",
"situacaoCadastro": "criada" },
{ "ref": "func-883", "pessoaId": "cmg7x9a1b0003hijk",
"nome": "Maria de Souza Lima", "cpf": "98765432100",
"situacaoCadastro": "reaproveitada" }
],
"itens": [
{ "itemId": "cmg7xb2c30004lmno", "ref": "func-882", "nr": "NR10",
"precoCentavos": 4500, "status": "aguardando_pagamento" },
{ "itemId": "cmg7xb2c30005pqrs", "ref": "func-883", "nr": "NR10",
"precoCentavos": 4500, "status": "aguardando_pagamento" },
{ "itemId": "cmg7xb2c30006tuvw", "ref": "func-883", "nr": "NR35",
"precoCentavos": 4500, "status": "aguardando_pagamento" }
],
"avisos": [
{ "ref": "func-883", "codigo": "JA_POSSUI_CERTIFICADO", "nr": "NR10",
"validoAte": "2027-03-04",
"mensagem": "Esta pessoa já tem um certificado NR10 válido até 04/03/2027." }
]
}
Três campos que merecem atenção:
situacaoCadastro—criadaoureaproveitada. Quando o trabalhador já existe na nossa base (compra anterior, ou outro cliente nosso), reaproveitamos a conta dele.nome— é o nome que vamos imprimir. Numa conta reaproveitada, o nome que já estava cadastrado prevalece sobre o que você enviou. Compare com o seu e, se divergir, fale com a gente antes da emissão: depois do primeiro certificado assinado o nome fica travado.avisos[]— não bloqueia nada, e pode vir vazio. Serve para você avisar seu cliente antes de cobrar por um certificado que ele já tem.
Os ids (pedidoId, pessoaId, itemId) são identificadores opacos — não presuma formato nem
sequência. Guarde-os como texto.
linkPagamento é o que você entrega ao seu cliente. Ele abre a página, escolhe PIX, boleto ou
cartão, e paga. O link é aberto: não exige cadastro prévio nem senha.
4.3 GET /pedidos/{pedidoId}
Também aceita GET /pedidos?externalRef=PO-2026-1234.
É a fonte da verdade sobre o estado atual. Os webhooks são notificações; havendo qualquer divergência, vale esta consulta.
{
"pedidoId": "cmg7x2k9a0001abcd",
"externalRef": "PO-2026-1234",
"status": "em_andamento",
"pagoEm": "2026-09-16T18:40:02Z",
"itens": [
{
"itemId": "it_01",
"ref": "func-882",
"status": "concluido",
"pessoa": { "nome": "João Carlos da Silva", "cpf": "12345678909" },
"nr": "NR10",
"certificado": {
"codigoValidacao": "A1B2C3D4E5",
"validacaoUrl": "https://www.regulaseg.com.br/validar/A1B2C3D4E5",
"titulo": "Certificado de Segurança em Instalações e Serviços em Eletricidade",
"cargaHoraria": 40,
"baseLegal": "De acordo com a NR-10, aprovada pela Portaria MTE nº 598…",
"emitidoEm": "2026-09-16",
"validoAte": "2028-09-16",
"assinadoEm": "2026-09-16T19:12:08Z"
}
},
{
"itemId": "it_03",
"ref": "func-883",
"status": "aguardando_assinatura",
"pessoa": { "nome": "Maria de Souza Lima", "cpf": "98765432100" },
"nr": "NR35",
"certificado": null
}
]
}
O validacaoUrl é exatamente a URL do QR code impresso no certificado. Qualquer pessoa pode
abri-la para conferir a autenticidade — é o link que você guarda e exibe dentro da sua plataforma.
5. Estados
status do item |
Significa |
|---|---|
aguardando_pagamento |
Pedido criado, cobrança em aberto |
pago |
Pagamento confirmado |
emitindo |
Gerando o certificado |
aguardando_aceite |
Falta o trabalhador (ou o gestor) declarar o treinamento concluído |
aguardando_assinatura |
Falta assinar o certificado |
concluido |
Assinado e liberado — é este que vale |
cancelado |
Pedido estornado ou matrícula cancelada |
O pedido tem um status próprio: aguardando_pagamento, em_andamento, concluido, cancelado.
Sobre o aceite e a assinatura: o certificado só é válido depois que alguém declara que o treinamento foi realizado e assina o documento. Quem faz isso é o próprio trabalhador, que recebe o link por WhatsApp e e-mail, ou o gestor da empresa, em nome do trabalhador — nesse caso o nome do gestor fica registrado como responsável. As duas formas já funcionam, sem nenhuma configuração da sua parte.
Compra grande? Numa compra de 50 ou 200 pessoas, o gestor da empresa resolve tudo de uma vez: a plataforma tem uma tela onde ele aceita os termos de todos os funcionários em lote e assina os certificados ele mesmo. Nenhum trabalhador precisa entrar. É o caminho normal para lote grande.
Quando o pedido para — e de quem é a vez
| Estado | Tempo normal | Quem está travado | O que fazer | Abrir chamado? |
|---|---|---|---|---|
aguardando_pagamento, link nunca aberto |
— | você | entregar o link ao seu cliente | não |
aguardando_pagamento, link aberto |
horas no PIX e cartão, até 3 dias úteis no boleto | seu cliente | cobrar o cliente | não |
pago sem emitindo virar certificado em 1 h |
< 1 h | nós | — | sim, com o requestId |
aguardando_aceite |
< 48 h | o gestor ou o trabalhador | pedir que entre e declare o treinamento | não |
aguardando_assinatura |
< 48 h | o trabalhador | pedir que confira o WhatsApp do número cadastrado | só se o número estiver certo e nada tiver chegado |
concluido sem webhook recebido |
— | você | conferir por GET /pedidos/{id} |
não |
Frases que seu cliente vai ver — e que o seu suporte vai ouvir repetidas. Reconhecer estas três evita escalonamento:
- "O link de assinatura já foi enviado há X minutos. Aguarde um pouco antes de pedir outro." — há um intervalo mínimo de 10 minutos entre reenvios, para não virar spam no WhatsApp da pessoa.
- "Este certificado já teve várias vias de assinatura abertas." — depois de 5 tentativas o envio trava e precisa passar pelo nosso suporte. Quando isso acontece, o problema quase nunca é o link: é o número de telefone.
- "Não lembro minha senha." — a plataforma tem recuperação por e-mail, e o gestor da empresa também consegue reenviar o acesso de qualquer funcionário pela área de equipe.
6. Webhooks
Notificamos a sua URL a cada etapa concluída.
| Evento | Quando |
|---|---|
order.paid |
O pagamento foi confirmado e o processo começou |
certificate.issued |
O PDF foi gerado — ainda não está assinado |
term.accepted |
O treinamento foi declarado concluído |
certificate.signed |
Certificado assinado e liberado — vem completo |
order.completed |
Todas as pessoas do pedido concluíram |
order.cancelled |
Pedido estornado — invalida certificados já entregues |
order.cancelledmerece tratamento. Se um pedido é estornado depois de os certificados já terem sido emitidos, eles deixam de valer: ovalidacaoUrlpassa a exibir "Certificado cancelado" para quem consultar. Remova o documento da sua plataforma ao receber este evento — senão seu cliente exibe um certificado que a validação pública desmente.
Corpo
{
"id": "evt_01J8ZQ7X3M",
"evento": "certificate.signed",
"criadoEm": "2026-09-16T19:12:09Z",
"pedidoId": "cmg7x2k9a0001abcd",
"externalRef": "PO-2026-1234",
"itemId": "it_01",
"ref": "func-882",
"status": "concluido",
"pessoa": { "nome": "João Carlos da Silva", "cpf": "12345678909" },
"nr": "NR10",
"certificado": {
"codigoValidacao": "A1B2C3D4E5",
"validacaoUrl": "https://www.regulaseg.com.br/validar/A1B2C3D4E5",
"titulo": "Certificado de Segurança em Instalações e Serviços em Eletricidade",
"cargaHoraria": 40,
"baseLegal": "De acordo com a NR-10, aprovada pela Portaria MTE nº 598…",
"emitidoEm": "2026-09-16",
"validoAte": "2028-09-16",
"assinadoEm": "2026-09-16T19:12:08Z"
}
}
Cabeçalhos
Content-Type: application/json
X-Regulaseg-Evento: certificate.signed
X-Regulaseg-Entrega: evt_01J8ZQ7X3M
X-Regulaseg-Assinatura: t=1758038531,v1=9f8c2b...
Como validar a assinatura
HMAC-SHA256 sobre a string "<timestamp>.<corpo cru>", com o segredo de webhook que entregamos.
const crypto = require("node:crypto");
// Use o corpo CRU, antes de qualquer parser de JSON.
// No Express: app.post("/webhook", express.raw({ type: "application/json" }), handler)
function validar(corpoCru, assinatura, segredo) {
const partes = Object.fromEntries(assinatura.split(",").map((p) => p.split("=")));
const t = Number(partes.t);
// 1) Anti-replay: recusa eventos com mais de 5 minutos.
if (Math.abs(Date.now() / 1000 - t) > 300) return false;
// 2) Recalcula e compara em tempo constante.
const esperado = crypto.createHmac("sha256", segredo).update(`${t}.${corpoCru}`).digest("hex");
const a = Buffer.from(esperado, "hex");
const b = Buffer.from(partes.v1, "hex");
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Três erros comuns: validar sobre o JSON reserializado em vez dos bytes recebidos; comparar com ==
em vez de comparação em tempo constante; e ignorar o timestamp, o que deixa um evento capturado ser
reenviado para sempre.
Entrega
- Responda
2xxem menos de 5 segundos e processe em segundo plano. - Repetimos em 1min, 5min, 30min, 2h e 6h. Depois disso o evento fica registrado e pode ser reenviado manualmente a pedido.
- O mesmo evento pode chegar duas vezes — descarte repetidos pelo
X-Regulaseg-Entrega. - A ordem não é garantida. Em caso de dúvida, consulte
GET /pedidos/{id}. - Não seguimos redirecionamentos: a URL precisa ser
httpse responder diretamente.
7. Catálogo
As NRs disponíveis hoje. O preço é o que negociamos com você — consulte GET /cursos.
| Código | Curso | Carga | Validade | Prático presencial |
|---|---|---|---|---|
NR01 |
Disposições Gerais e GRO | 4 h | 24 meses | não |
NR05 |
CIPA | 20 h | 24 meses | não |
NR06 |
EPI | 4 h | 24 meses | não |
NR10 |
Instalações e Serviços com Eletricidade | 40 h | 24 meses | não |
NR11 |
Transporte e Movimentação de Materiais | 16 h | 24 meses | não |
NR12 |
Máquinas e Equipamentos | 8 h | 24 meses | não |
NR18 |
Indústria da Construção | 6 h | 24 meses | não |
NR20 |
Inflamáveis e Combustíveis | 8 h | 24 meses | não |
NR32 |
Serviços de Saúde | 8 h | 24 meses | não |
NR33 |
Espaços Confinados | 16 h | 12 meses | sim |
NR34 |
Construção e Reparação Naval | 8 h | 12 meses | não |
NR35 |
Trabalho em Altura | 8 h | 24 meses | sim |
8. Erros
| HTTP | erro |
O que fazer |
|---|---|---|
| 400 | DADOS_INVALIDOS |
Corrigir o campo apontado em detalhes |
| 401 | CHAVE_INVALIDA |
Conferir a chave |
| 403 | PARCEIRO_INATIVO |
Falar com a REGULASEG |
| 404 | NAO_ENCONTRADO |
Conferir o id |
| 409 | PESSOA_DUPLICADA |
CPF ou e-mail repetido no lote |
| 422 | CURSO_INDISPONIVEL |
NR fora do seu catálogo — reler GET /cursos |
| 422 | PRECO_NAO_CADASTRADO |
NR sem preço acordado. Falar com a REGULASEG antes de vender |
| 422 | LOTE_GRANDE_DEMAIS |
Dividir o pedido |
| 429 | LIMITE_EXCEDIDO |
Aguardar e repetir |
| 500 | ERRO_INTERNO |
Repetir; se persistir, abrir chamado com o requestId |
Sobre PESSOA_DUPLICADA: cada trabalhador precisa de um e-mail próprio. Um e-mail já vinculado a
outra pessoa que tenha certificado emitido não pode ser reaproveitado — é o que impede certificado
sair no nome errado.
9. Para começar
Precisamos de você:
- Razão social, CNPJ e responsável técnico (nome, e-mail, telefone).
- A URL que vai receber os webhooks (
https). - As NRs que pretende vender, para fecharmos a tabela de preço.
Entregamos:
- O seu código de parceiro e a chave de API.
- O segredo de assinatura dos webhooks.
- A tabela de preço acordada, já ativa no
GET /cursos.
Dúvidas técnicas: fale com a gente, com o requestId da chamada quando houver.
