Para programadores
API para parceiros
Envie-nos um cliente com o seu próprio identificador pseudónimo - sem e-mail, nome ou outros dados pessoais - e consulte a qualquer momento o estado da sua formação. Serve como verificação de conformidade antes de um contrato, de um depósito ou de um pagamento.
Versão 1.3.2 · JSON sobre HTTPS · OpenAPI
Como funciona
A API é igual para todos os parceiros. Em cinco passos:
- Ativamos a API para a sua empresa; na sua administração, cria uma chave API no separador API.
- Quando um cliente deve receber formação, o seu sistema chama POST /v1/users com o seu identificador do cliente.
- Criamos um perfil sem e-mail e devolvemos um link de acesso (entryUrl); mostra-o ao cliente como um botão.
- O cliente clica nele e entra diretamente no curso.
- Consulta o estado a qualquer momento através de GET /v1/users/{identifier}, ou comunicamo-lo ao seu servidor por webhook.
Quanto ao identificador, é o responsável pelo tratamento; nós tratamos apenas dados pseudonimizados. Nunca envie como identificador um e-mail ou um nome - a API recusa um endereço de e-mail com o erro 422.
Endereço e autenticação
Cada chamada vai por HTTPS para o endereço abaixo e leva a sua chave API no cabeçalho Authorization.
https://api.responsiblo.com Authorization: Bearer rsb_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- rsb_live_... abre o seu programa de produção, rsb_test_... o seu programa de teste (sandbox).
- A chave é mostrada apenas uma vez, quando é criada; guardamos apenas a sua impressão digital. Guarde-a como segredo no seu servidor - nunca num navegador nem numa aplicação.
- A chave tem permissões: read (o estado e a lista de pessoas, o certificado) e write (o envio e a anonimização de pessoas). Pode estar limitada aos seus endereços IP e ter uma validade.
- Substituição: cria uma chave nova, a antiga continua válida durante 7 dias e depois expira.
- As respostas nunca são guardadas em cache (Cache-Control: no-store) e a API não aceita chamadas a partir de um navegador (sem CORS).
POST /v1/users
Envia uma pessoa para o programa da chave (permissão write).
curl -X POST https://api.responsiblo.com/v1/users \
-H "Authorization: Bearer $RSB_KEY" \
-H "Content-Type: application/json" \
-d '{"identifier":"client-48213","language":"cs","label":"campaign-2026-10"}'
| Campo | Obrigatório | Significado |
|---|---|---|
identifier |
sim | O seu pseudónimo da pessoa, 1 a 64 caracteres A-Z a-z 0-9 . _ : @ -; nunca um endereço de e-mail (recusado com 422). |
program |
não | Código do programa; se o indicar, tem de ser o programa da chave. |
language |
não | Idioma do curso (cs, en, ...); por predefinição, o primeiro idioma do programa. |
label |
não | A sua etiqueta - uma coorte ou uma campanha, 1 a 64 caracteres, nunca um dado pessoal. |
expiresAt |
não | Último dia de acesso, AAAA-MM-DD. |
201 Created para uma pessoa nova, 200 OK quando o identificador já existe - nada muda, a chamada pode ser repetida em segurança. O corpo é o estado abaixo, com entryUrl. Um limite esgotado de pessoas ou de licenças do programa devolve 403.
GET /v1/users/{identifier}
Estado de uma pessoa (permissão read): o que uma verificação de conformidade precisa, nada mais.
curl https://api.responsiblo.com/v1/users/client-48213 -H "Authorization: Bearer $RSB_KEY"
{
"identifier": "client-48213",
"program": "your-program",
"status": "in_progress",
"progress": 43,
"lessonsCompleted": 3,
"lessonsTotal": 7,
"quizScore": null,
"label": "campaign-2026-10",
"createdAt": "2026-10-20T10:02:11Z",
"startedAt": "2026-10-20T10:05:40Z",
"completedAt": null,
"lastActivityAt": "2026-10-20T10:31:40Z",
"expiresAt": null,
"certificate": null,
"entryUrl": "https://your-company.responsiblo.com/entry/..."
}
status | Significado |
|---|---|
enrolled |
enviada, ainda não entrou |
started |
entrou, ainda não concluiu nada |
in_progress |
tem lições concluídas, o programa ainda não |
completed |
o programa está concluído (completedAt) |
expired |
o acesso terminou (expiresAt passou; uma pessoa na sandbox termina ao fim de 7 dias) |
quizScore é o resultado do questionário final em %, assim que estiver concluído. As horas estão em UTC, ao segundo inteiro. O campo certificate contém o certificado da pessoa (ver abaixo); enquanto não o tiver, é null.
?include=detail
Acrescenta o progresso em cada curso e o resultado de cada questionário - nunca as respostas individuais.
"courses": [{"id": "733db340-...", "name": "Introduction", "progress": 40, "lessonsCompleted": 2, "lessonsTotal": 5, "completed": false}],
"quizzes": [{"id": "d2e72fd7-...", "name": "Quiz of the introduction", "score": 85, "completedAt": "2026-10-20T10:31:40Z"}]
GET /v1/users
Lista das pessoas que enviou para o programa da chave (permissão read), página a página: cada item tem a forma do estado acima. Opcionalmente status (apenas as pessoas nesse estado), limit (1 a 500, por predefinição 100) e cursor.
curl "https://api.responsiblo.com/v1/users?status=completed&limit=100" -H "Authorization: Bearer $RSB_KEY"
{
"items": [{ "identifier": "client-48213", "status": "completed", "...": "the state of GET /v1/users/{identifier}" }],
"nextCursor": "MjAyNi0xMC0yMFQxMDowMjoxMVp8...",
"limit": 100
}
curl "https://api.responsiblo.com/v1/users?status=completed&limit=100&cursor=MjAyNi0xMC0yMFQxMDowMjoxMVp8..." -H "Authorization: Bearer $RSB_KEY"
- Continue com cursor = nextCursor enquanto nextCursor não for null; o cursor é um texto opaco, nunca o construa por si.
- As pessoas surgem pelo momento do envio, numa ordem estável (também no mesmo momento), nenhuma duas vezes; as pessoas anonimizadas não constam da lista.
- Com o filtro status percorremos no máximo 2000 pessoas por página, pelo que uma página pode ter menos itens do que limit, ou mesmo nenhum - continue enquanto houver um nextCursor.
Certificado da pessoa
Assim que a pessoa conclui o programa, o curso emite-lhe um certificado - com o seu pseudónimo (a alcunha do perfil ID XXXXXX), sem nome e sem e-mail. Nada é enviado por e-mail; o estado da pessoa inclui o campo certificate com o número, as datas e a página pública de verificação, e o PDF é descarregado através de GET /v1/users/{identifier}/certificate.
"certificate": {
"number": "RSP-7KQ2-M4XH-9TWB",
"issuedAt": "2026-10-20T10:39:15Z",
"expiresAt": "2028-10-20T10:39:12Z",
"verifyUrl": "https://responsiblo.com/verify/RSP-7KQ2-M4XH-9TWB"
}
curl https://api.responsiblo.com/v1/users/client-48213/certificate -H "Authorization: Bearer $RSB_KEY" -o client-48213.pdf
- A página de verificação verifyUrl mostra apenas o pseudónimo, o programa, o parceiro e a validade - nunca o seu identificador.
- O PDF devolve application/pdf (permissão read). Sem certificado, a resposta é 404 certificateNotFound; enquanto o PDF ainda está a ser gerado, 404 certificatePdfNotReady com Retry-After.
- Um certificado revogado nunca é entregue (o campo certificate fica então null, o PDF 404); um certificado com a validade expirada continua a ser uma prova verdadeira e é entregue.
- Um webhook anuncia o certificado com o evento certificate.issued (logo após user.completed).
DELETE /v1/users/{identifier}
Anonimiza uma pessoa (permissão write): do perfil desaparecem o seu identificador, a etiqueta e todas as mensagens de webhook que o mencionam; os links de acesso deixam de ser válidos. O certificado e o resultado do curso ficam sob o número do certificado - como prova de conformidade.
curl -X DELETE https://api.responsiblo.com/v1/users/client-48213 -H "Authorization: Bearer $RSB_KEY" HTTP/1.1 204 No Content
Resposta 204 sem corpo; cada chamada seguinte com o mesmo identificador devolve 404 userNotFound, pelo que a repetição é segura. Pode depois voltar a enviar o mesmo identificador como uma pessoa nova.
Link de acesso
Mostre entryUrl à pessoa (um botão Iniciar o curso no seu sistema). Inicia a sessão da pessoa no curso - sem e-mail e sem palavra-passe.
O link é válido durante 30 dias e pode ser usado várias vezes; cada chamada GET /v1/users/{identifier} devolve um novo. Nunca o envie a outra pessoa: quem tem o link entra como essa pessoa.
Webhooks
No separador API da sua administração, configura um webhook por programa: um endereço HTTPS público do seu servidor e os eventos. A partir daí enviamos-lhe um POST com JSON - apenas identificadores e estados, nunca o link de acesso.
| Evento | Quando |
|---|---|
user.enrolled |
a pessoa foi enviada (a primeira vez que o seu webhook a conhece) |
user.started |
a pessoa entrou no curso |
user.completed |
a pessoa concluiu o programa |
certificate.issued |
a pessoa obteve um certificado; data contém certificate (o número, as datas, verifyUrl) |
user.expired |
o acesso da pessoa terminou |
POST https://your-server.example/responsiblo/webhook
Content-Type: application/json
X-Responsiblo-Event: user.completed
X-Responsiblo-Delivery: 5b0c1f9e-2d1a-4a57-9a3e-0d6c9c1f2b77
X-Responsiblo-Signature: t=1792492800,v1=3f1c...e9
{
"id": "5b0c1f9e-2d1a-4a57-9a3e-0d6c9c1f2b77",
"type": "user.completed",
"createdAt": "2026-10-20T10:40:00Z",
"apiVersion": "1.3.2",
"program": "your-program",
"data": {
"identifier": "client-48213",
"status": "completed",
"progress": 100,
"lessonsCompleted": 7,
"lessonsTotal": 7,
"quizScore": 85,
"label": "campaign-2026-10",
"startedAt": "2026-10-20T10:05:40Z",
"completedAt": "2026-10-20T10:39:12Z",
"expiresAt": null
}
}
Assinatura
Cada mensagem leva o cabeçalho X-Responsiblo-Signature: t=<tempo Unix>,v1=<HMAC-SHA256 do texto t.corpo com o segredo do webhook, hex>. O segredo (whsec_...) é mostrado uma vez, quando o webhook é criado. Antes de confiar numa mensagem, verifique a assinatura e a idade de t; use X-Responsiblo-Delivery como chave de idempotência.
// PHP: $secret = "whsec_...", $header = X-Responsiblo-Signature, $body = the raw body
preg_match('/^t=(\d+),v1=([0-9a-f]{64})$/', $header, $m);
$valid = $m
&& abs(time() - (int) $m[1]) <= 300
&& hash_equals(hash_hmac('sha256', $m[1] . '.' . $body, $secret), $m[2]);
Entrega e repetição
Entregue = resposta 2xx em 10 segundos. Caso contrário, tentamos de novo ao fim de 1 minuto, 5 minutos, 30 minutos, 2 horas e 12 horas, e depois desistimos. Não seguimos redirecionamentos.
20 mensagens não entregues seguidas desativam o webhook até que o volte a ativar; as mensagens desse período ficam à espera. O botão Test envia um ping; o registo de entregas encontra-se na sua administração.
O evento certificate.issued acrescenta-se a um webhook nas respetivas definições; um webhook criado antes da versão 1.2 não o recebe por si só.
Erros
Cada erro tem uma única forma: status, code, reason e message; um erro 422 acrescenta errors (campo - o que está errado).
{ "status": "error", "code": 422, "reason": "invalidBody", "message": "The body is not valid.",
"errors": { "identifier": "identifier must be a pseudonym of the partner, never an e-mail address" } }
| HTTP | reason | O que fazer |
|---|---|---|
| 400 | invalidJson |
envie um único objeto JSON |
| 401 | missingToken, invalidToken |
envie uma chave válida (uma chave revogada e uma expirada têm o mesmo aspeto); o cabeçalho WWW-Authenticate indica Bearer |
| 403 | scopeDenied, ipNotAllowed, apiDisabled, partnerInactive, spaceUnavailable, httpsRequired, userLimitReached, seatsExhausted |
a chave não tem permissão para isto, a API está desativada para a sua empresa, ou o programa está cheio |
| 404 | userNotFound, notFound |
no programa da chave não existe nenhuma pessoa com este identificador (nem anonimizada) |
| 404 | certificateNotFound, certificatePdfNotReady |
a pessoa ainda não tem certificado, ou o PDF está a ser gerado - tente de novo após Retry-After |
| 409 | identifierTaken |
o identificador pertence a uma pessoa de outro programa |
| 422 | invalidBody, invalidParameter |
ver errors (um campo do corpo ou um parâmetro da consulta - o que está errado) |
| 429 | rateLimited |
aguarde Retry-After segundos |
| 500 | internalError |
tente mais tarde; indique incidentId ao nosso apoio |
Para programas e agentes
- Decida com base em code e reason, nunca no texto de message; errors é um objeto campo -> o que está errado.
- Repita apenas 429, 500 e certificatePdfNotReady, e só após Retry-After segundos (caso contrário, com um intervalo crescente); não repita outros 4xx além de 429 sem corrigir a chamada.
- POST /v1/users é idempotente por identifier (201 da primeira vez, depois 200); DELETE devolve 204 da primeira vez e 404 depois - ambas podem ser repetidas em segurança.
- Elimine duplicados dos webhooks por X-Responsiblo-Delivery; a ordem das mensagens não é garantida, decide o estado em data.
Guia do empréstimo
O guia do empréstimo é um curso curto para o requerente junto de um mutuante: antes de assinar o contrato, o requerente percorre três lições, oito situações práticas e, eventualmente, um questionário, tudo com os números da sua própria proposta, e no fim confirma a proposta. Em cada ecrã, o requerente pode pedir uma explicação. Envia a proposta através da API, recebe um link de acesso e um webhook comunica-lhe o resultado.
Ativamos o guia do empréstimo mediante acordo consigo.
Também aqui o requerente é apenas o seu perfil pseudónimo de POST /v1/users. A proposta é identificada pelas suas referências (externalApplicationId, offerReference) e os documentos apenas por um link com impressão digital SHA-256 - nunca um nome, e-mail, número de identificação pessoal, número de conta ou telefone. responsiblo não aprova o empréstimo, não descarrega nem guarda os documentos, não verifica a identidade e não emite certificado para o guia.
- Cria o perfil do requerente: POST /v1/users com o seu pseudónimo.
- Envia a proposta: POST /v1/users/{identifier}/loan-offers; a resposta 201 traz entryUrl.
- Entrega entryUrl ao requerente pelo seu próprio canal autenticado. O link é válido durante 30 dias e pode ser usado várias vezes; o guia mostra os números da proposta do requerente.
- O fim é-lhe comunicado por webhook (loanGuide.completed, loanGuide.assistanceRequested e outros).
- Consulta o estado através de GET …/loan-offers/{offerReference} e o registo para o seu processo através de GET …/evidence. Proposta alterada = nova proposta com supersedes, pedido retirado = POST …/cancel.
Até à ativação, as operações do guia respondem 404 notFound ou 409 loanGuideNotConfigured. A permissão write envia e cancela a proposta, read lê o estado e o registo.
POST /v1/users/{identifier}/loan-offers
Envia uma proposta para o perfil do requerente (permissão write). O cabeçalho opcional Idempotency-Key tem 1 a 255 caracteres ASCII visíveis. Exemplo: empréstimo de 10 000 CZK, 10 800 CZK a pagar num único pagamento 30 dias após o desembolso, TAEG 155,10 %.
curl -X POST https://api.responsiblo.com/v1/users/applicant-30417/loan-offers \
-H "Authorization: Bearer $RSB_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: offer-30417-1" \
-d '{
"externalApplicationId": "APP-30417",
"offerReference": "OFF-30417-1",
"locale": "cs-CZ",
"currency": "CZK",
"principalMinor": 1000000,
"disbursedAmountMinor": 1000000,
"totalPayableMinor": 1080000,
"aprPercent": "155.10",
"interestRate": { "percent": "8", "period": "month" },
"repayment": {
"type": "singlePayment",
"amountMinor": 1080000,
"due": { "kind": "relative", "days": 30, "anchor": "disbursement" }
},
"documents": [
{ "role": "precontract_information", "reference": "DOC-PRE-30417", "title": "Předsmluvní informace",
"url": "https://documents.lender.example/pre/30417.pdf",
"sha256": "623f4a37e444268c076896d6c2f389b46f568d1a26539b013f2ba25d03846f72" },
{ "role": "contract_package", "reference": "DOC-CON-30417", "title": "Smlouva a podmínky",
"url": "https://documents.lender.example/contract/30417.pdf",
"sha256": "9c7bfe0077d1189914f0e1c483c961f4c5b36e9892385f3d2ab6168e0c088aa6" }
],
"validUntil": "2026-11-15T18:00:00Z"
}'
HTTP/1.1 201 Created
{
"offerReference": "OFF-30417-1",
"externalApplicationId": "APP-30417",
"offerStatus": "active",
"guideStatus": "created",
"validUntil": "2026-11-15T18:00:00Z",
"snapshotSha256": "8055bfa3c5f2c163691b85785eaf61221169a123bed67aff2c1dbaf2a8e44e7e",
"entryUrl": "https://your-company.responsiblo.com/entry/...",
"createdAt": "2026-11-10T09:14:05Z"
}
| Campo | Obrigatório | Significado |
|---|---|---|
externalApplicationId |
sim | O seu número do pedido, 1 a 128 caracteres A-Z a-z 0-9 . _ : -; nunca um endereço de e-mail. |
offerReference |
sim | A sua referência da proposta, as mesmas regras que externalApplicationId. |
locale |
sim | Língua e país do guia: cs-CZ. |
currency |
sim | Moeda: CZK. |
principalMinor |
sim | Montante do empréstimo em haléř (centésimos de coroa), número inteiro de 1 a 10 000 000 000. |
disbursedAmountMinor |
sim | Montante desembolsado em haléř; tem de ser igual ao montante do empréstimo. |
totalPayableMinor |
sim | Montante total a pagar em haléř; no mínimo o montante do empréstimo e exatamente a soma dos pagamentos. |
aprPercent |
sim | TAEG em percentagem como texto ("155.10"), calculada e garantida por si. Custos positivos com TAEG 0 são recusados pela API. |
interestRate |
não | Taxa de juro {percent, period}, period = year, month ou day. |
repayment |
sim | Reembolso: singlePayment {amountMinor, due} com data (kind date) ou número de dias desde o desembolso (kind relative, 1 a 365), ou installments {schedule: [{date, amountMinor}]} com 1 a 360 prestações por ordem crescente, nenhuma no passado. O tipo tem de corresponder ao produto definido para o seu guia. |
documents |
sim | 2 a 10 documentos {role, reference, title, url, sha256}; cobertos os papéis que as definições do seu guia exigem (por predefinição precontract_information e contract_package). url apenas HTTPS num host autorizado nas definições do seu guia, no máximo 2 048 caracteres, sem credenciais; sha256 = 64 caracteres hexadecimais declarados por si. |
validUntil |
sim | Validade da proposta, RFC 3339 com desvio horário, no futuro e no máximo 7 dias à frente. |
supersedes |
não | offerReference da proposta ativa do mesmo perfil que a nova proposta substitui. |
returnUrl |
não | Opcional: o endereço para onde a página «Concluído» devolve o requerente no fim do guia. Apenas HTTPS absoluto, no máximo 2048 caracteres, sem credenciais; substituímos os símbolos {offerReference} e {externalApplicationId} pelas referências da proposta. Sem ele aplica-se o endereço de regresso das definições do seu guia. |
O mesmo corpo novamente (com as mesmas referências ou a mesma Idempotency-Key) devolve 200 com a proposta existente e um novo entryUrl; outro corpo com elas devolve 409 offerConflict. Um perfil tem uma proposta ativa: outra sem supersedes devolve 409 activeOfferExists, um supersedes errado 409 notSupersedable. As definições do seu guia (questionário, contacto) ficam nesse momento bloqueadas para a proposta.
Estado, registo e cancelamento
GET /v1/users/{identifier}/loan-offers/{offerReference}- estado (permissão read): offerStatus (active, expired, superseded, cancelled), guideStatus (created, in_progress, completed), lições concluídas, prática, questionário (null quando está desativado) e os momentos da apresentação da proposta, da confirmação e do pedido de explicação. Nunca as respostas, os valores da proposta nem o link. A conclusão mantém-se, mesmo que a proposta expire mais tarde.GET /v1/users/{identifier}/loan-offers/{offerReference}/evidence- registo para o seu processo (permissão read): schemaVersion loan-guide-evidence/1, instantâneo da sua proposta com a impressão digital snapshotSha256, edição do curso com as impressões digitais das lições, eventos pela ordem de sequence, cada resposta com todas as tentativas, a confirmação e limitations - o que o registo não prova (apresentado não significa lido, a identidade é afirmada por si, documentos apenas por referência, nenhum certificado, nenhuma aprovação do empréstimo).POST /v1/users/{identifier}/loan-offers/{offerReference}/cancel- cancela uma proposta ativa (permissão write), reasonCode = withdrawn_by_provider ou application_closed; 200 devolve o estado, uma proposta que não está ativa ou cujo guia está concluído devolve 409 notActive.
curl https://api.responsiblo.com/v1/users/applicant-30417/loan-offers/OFF-30417-1 -H "Authorization: Bearer $RSB_KEY"
{
"offerReference": "OFF-30417-1",
"externalApplicationId": "APP-30417",
"offerStatus": "active",
"guideStatus": "completed",
"quizEnabled": true,
"lessonsCompleted": 3,
"lessonsTotal": 3,
"practiceCompleted": true,
"quizPassed": true,
"offerPresentedAt": "2026-11-10T18:32:47Z",
"confirmedAt": "2026-11-10T18:34:02Z",
"completedAt": "2026-11-10T18:34:02Z",
"assistanceRequested": false,
"assistanceRequestedAt": null,
"validUntil": "2026-11-15T18:00:00Z",
"evidenceErased": false,
"...": "..."
}
curl -X POST https://api.responsiblo.com/v1/users/applicant-30417/loan-offers/OFF-30417-1/cancel \
-H "Authorization: Bearer $RSB_KEY" \
-H "Content-Type: application/json" \
-d '{"reasonCode":"withdrawn_by_provider"}'
?externalApplicationId= só é necessário quando uma offerReference pertence a vários pedidos do perfil (caso contrário, 409 ambiguousOfferReference).
Webhooks do guia
O webhook do programa (ver Webhooks) recebe os eventos do guia sem subscrição própria. A assinatura, a entrega e a repetição são as mesmas dos outros eventos; data contém identifier, offerReference, externalApplicationId, guideStatus, occurredAt e sequence (a ordem dos eventos de uma proposta) - nunca o registo, os valores da proposta nem o link de acesso.
| Evento | Quando |
|---|---|
loanGuide.completed |
o requerente percorreu o guia e confirmou a proposta |
loanGuide.assistanceRequested |
o requerente pediu uma explicação (ligue ao requerente) |
loanGuide.expired |
o validUntil da proposta foi ultrapassado |
loanGuide.superseded |
uma nova proposta substituiu-a (supersedes) |
loanGuide.cancelled |
cancelou a proposta |
POST https://your-server.example/responsiblo/webhook
Content-Type: application/json
X-Responsiblo-Event: loanGuide.completed
X-Responsiblo-Delivery: 0f6e2a4c-91d3-4b8e-a7c5-3e2d1b9f6a08
X-Responsiblo-Signature: t=1794335647,v1=8b2d...4c
{
"id": "0f6e2a4c-91d3-4b8e-a7c5-3e2d1b9f6a08",
"type": "loanGuide.completed",
"createdAt": "2026-11-10T18:34:07Z",
"apiVersion": "1.3.2",
"program": "your-program",
"data": {
"identifier": "applicant-30417",
"offerReference": "OFF-30417-1",
"externalApplicationId": "APP-30417",
"guideStatus": "completed",
"occurredAt": "2026-11-10T18:34:02Z",
"sequence": 23
}
}
Cada evento chega a um webhook no máximo uma vez (chave de idempotência = X-Responsiblo-Delivery). Um webhook criado mais tarde não reproduz eventos anteriores, e os eventos com mais de 28 dias já não são comunicados.
Conservação do registo
Quando o percurso de uma proposta termina (proposta concluída, cancelada, expirada ou substituída), corre o prazo de conservação das definições do seu guia (por predefinição 30 dias). Depois, o registo é apagado: GET …/evidence devolve 410 evidenceErased e o estado continua a responder com evidenceErased: true, as referências e os momentos. Uma proposta ativa nunca é apagada. Descarregue o registo que tem de conservar logo após loanGuide.completed.
Erros do guia
Os erros têm a forma da API acima. Além disso, para o guia:
| HTTP | reason | O que fazer |
|---|---|---|
| 404 | offerNotFound |
o perfil não tem essa proposta (userNotFound = o perfil não existe) |
| 409 | offerConflict, activeOfferExists, notSupersedable |
as referências ou a Idempotency-Key já pertencem a outro corpo, ou o perfil tem outra proposta ativa - envie supersedes |
| 409 | loanGuideNotConfigured |
o guia não está ativado para o seu programa - escreva-nos |
| 409 | ambiguousOfferReference |
acrescente ?externalApplicationId= |
| 409 | notActive |
a proposta não está ativa ou o seu guia está concluído |
| 410 | evidenceErased |
o registo foi apagado após o prazo de conservação, o estado mantém-se |
| 422 | invalidOffer |
errors = {caminho: código[,código]} com o caminho no corpo (repayment.schedule[2].date, documents[0].url); os códigos na tabela abaixo |
| 422 | invalidBody |
supersedes, Idempotency-Key ou corpo do cancelamento |
errors | Códigos do erro invalidOffer |
|---|---|
required |
o campo está em falta |
invalidFormat |
forma errada (tipo, padrão, comprimento, link sem HTTPS ou com credenciais) |
outOfRange |
fora do intervalo permitido (montante, número de documentos, de prestações ou de dias) |
notEqualPrincipal |
o montante desembolsado não é igual ao montante do empréstimo |
sumMismatch |
a soma dos pagamentos não é igual ao montante total a pagar |
belowPrincipal |
o montante total a pagar é inferior ao montante do empréstimo |
aprContradiction |
TAEG 0 com custos positivos |
typeMismatch |
o tipo de reembolso não corresponde ao produto definido para o seu guia |
missingRole |
falta um documento com um papel que as definições do seu guia exigem |
hostNotAllowed |
o link de um documento aponta para um host que as definições do seu guia não autorizam |
notAscending |
as datas das prestações não são crescentes ou repetem-se |
inPast |
a data de uma prestação ou validUntil está no passado |
tooFar |
validUntil está mais de 7 dias à frente |
unsupported |
valor não suportado (locale, currency, type, period, kind) |
unknownField |
campo que a API não conhece |
looksLikeEmail |
a referência parece um endereço de e-mail |
Um erro nunca repete um valor que enviou. Exemplo: a mesma proposta com um pagamento de 10 700 CZK em vez de 10 800 CZK e uma validade de 9 dias:
"repayment": { "type": "singlePayment", "amountMinor": 1070000, "due": { "kind": "relative", "days": 30, "anchor": "disbursement" } },
"validUntil": "2026-11-19T18:00:00Z"
HTTP/1.1 422 Unprocessable Entity
{
"status": "error",
"code": 422,
"reason": "invalidOffer",
"message": "The offer contains invalid data.",
"errors": {
"repayment.amountMinor": "sumMismatch",
"validUntil": "tooFar"
}
}
Limites
120 chamadas por minuto e por chave. Após 30 chaves recusadas a partir de um mesmo endereço em dez minutos, o endereço aguarda 10 minutos.
Conservamos o registo de chamadas (sem corpos, o identificador apenas como impressão digital SHA-256) durante 180 dias, e as mensagens de webhook entregues e abandonadas durante 30 dias.
Estado e contrato
GET /v1/status- sem chave, devolve {"status":"ok","version":"1.3.2"}GET /openapi- sem chave, o documento OpenAPI 3 da API para parceiros
Sandbox
A chave de teste rsb_test_... abre o seu programa de teste com o mesmo curso. As pessoas nele terminam ao fim de 7 dias; o webhook do programa de teste está separado do de produção.
Histórico de versões
- 1.3.2 (2026-11) - Cada operação do documento OpenAPI tem um nome e uma descrição, e as operações estão organizadas em grupos. /v1/status e os webhooks indicam a versão 1.3.2. A forma dos pedidos e das respostas mantém-se inalterada.
- 1.3.1 (2026-10) - Correções sem alteração dos endpoints nem das suas respostas.
- 1.3.0 (2026-10) - Guia do empréstimo: POST /v1/users/{identifier}/loan-offers, estado, registo e cancelamento da proposta, webhooks loanGuide.*, conservação do registo. Campo opcional returnUrl da proposta (endereço de regresso próprio).
- 1.2.0 (2026-10) - GET /v1/users com paginação, o certificado da pessoa (campo certificate, GET /v1/users/{identifier}/certificate, evento certificate.issued), DELETE /v1/users/{identifier} (anonimização), identificador com 64 caracteres no máximo, conservação do registo.
- 1.1.0 (2026-10) - Chaves API, POST /v1/users, GET /v1/users/{identifier} com ?include=detail, link de acesso, webhooks, uma única forma de erros, estado público e OpenAPI, limites.
- 1.0.0 (2024) - GET /v1/user/{identifier} com o JWT da chave de parceiro.
Quer a API para a sua empresa? Escreva-nos