responsiblo

Developers

Partner API

Send a person to a responsiblo program under your own pseudonymous identifier - no e-mail, no name, no other personal data - and read back the state of the education. Use it as a compliance check before a contract, a deposit or a payout.

Version 1.3.2 · JSON over HTTPS · OpenAPI

How it works

The API is the same for every partner. In five steps:

  1. We switch the API on for your company; in your administration you create an API key in the tab API.
  2. When a client should be trained, your system calls POST /v1/users with your identifier of the client.
  3. We create a profile without an e-mail and answer an entry link (entryUrl); you show it to the client as a button.
  4. The client clicks it and is in the course at once.
  5. You read the state with GET /v1/users/{identifier} whenever you need it, or we tell your server through a webhook.

You are the controller of your identifier, we process pseudonymous data only. Never send an e-mail address or a name as the identifier - the API refuses an e-mail with the error 422.

Address and authentication

Every call goes over HTTPS to the address below and carries your API key in the header Authorization.

https://api.responsiblo.com
Authorization: Bearer rsb_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  • rsb_live_... opens your production program, rsb_test_... your sandbox program.
  • A key is shown once, when it is created; we keep only its fingerprint. Store it as a secret on your server - never in a browser or an app.
  • A key carries scopes: read (the state and the list of persons, the certificate) and write (sending and anonymizing persons). It may be limited to your IP addresses and have an expiry.
  • Rotation: you create a new key, the old one keeps working for 7 days, then it expires.
  • Answers are never cached (Cache-Control: no-store) and the API takes no calls from a browser (no CORS).

POST /v1/users

Sends a person to the program of the key (scope 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"}'
FieldRequiredMeaning
identifier yes Your pseudonym of the person, 1 to 64 characters A-Z a-z 0-9 . _ : @ -; never an e-mail address (refused with 422).
program no The code of the program; when given, it must be the program of the key.
language no The language of the course (cs, en, ...); by default the first language of the program.
label no Your label - a cohort or a campaign, 1 to 64 characters, never personal data.
expiresAt no The last day of the access, YYYY-MM-DD.

201 Created for a new person, 200 OK when the identifier is already there - nothing changes, the call is safe to repeat. The body is the state below, with entryUrl. The limit of persons or of the licence of the program answers 403.

GET /v1/users/{identifier}

The state of a person (scope read): what a compliance check needs, nothing more.

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/..."
}
statusMeaning
enrolled sent, never entered
started entered, nothing completed yet
in_progress lessons completed, the program not yet
completed the program is completed (completedAt)
expired the access ended (expiresAt passed; a sandbox person ends after 7 days)

quizScore is the result of the final quiz in % once it is finished. Moments are UTC with whole seconds. certificate carries the certificate of the person (see below), null until it has one.

?include=detail

Adds the progress of every course and the result of every quiz - never the single answers.

"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

The persons you sent into the program of the key (scope read), page by page: every item has the shape of the state above. Optional status (only the persons in that state), limit (1 to 500, default 100) and 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"
  • Go on with cursor = nextCursor while nextCursor is not null; the cursor is an opaque text, never build it yourself.
  • Persons come by the moment they were sent, in a stable order (also within the same moment), none twice; anonymized persons are not listed.
  • With the filter status at most 2000 persons are looked at for one page, so a page may hold fewer items than limit, even none - go on while there is a nextCursor.

The certificate of a person

Once the person completes the program, the course issues its certificate - under its pseudonym (the nickname of the profile ID XXXXXX), without a name and without an e-mail. Nothing is e-mailed; the state of the person carries certificate with the number, the moments and the public verification page, and you download the PDF from 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
  • The verification page verifyUrl shows the pseudonym, the program, the partner and the validity only - never your identifier.
  • The PDF answers application/pdf (scope read). Without a certificate the answer is 404 certificateNotFound, while the PDF is still being made 404 certificatePdfNotReady with Retry-After.
  • A revoked certificate is never handed out (certificate is then null, the PDF 404); an expired one stays a true record and is handed out.
  • A webhook announces the certificate with the event certificate.issued (right after user.completed).

DELETE /v1/users/{identifier}

Anonymizes a person (scope write): your identifier, the label and every webhook message naming it leave the profile; the entry links stop working. The certificate and the result of the course stay under the number of the certificate - as the compliance record.

curl -X DELETE https://api.responsiblo.com/v1/users/client-48213 -H "Authorization: Bearer $RSB_KEY"

HTTP/1.1 204 No Content

The answer is 204 without a body; every later call with the same identifier answers 404 userNotFound, so a repetition is safe. You may then send the same identifier again as a new person.

The entry link

Show entryUrl to the person (a button Start the course in your system). It signs the person into the course - no e-mail, no password.

The link holds for 30 days and may be used again; every GET /v1/users/{identifier} answers a fresh one. Never send it to anybody else: whoever has the link enters as that person.

Webhooks

In the tab API of your administration you set one webhook per program: a public HTTPS address of your server and the events. We then send a POST with JSON - identifiers and states only, never the entry link.

EventWhen
user.enrolled the person was sent (the first time your webhook knows it)
user.started the person entered the course
user.completed the person completed the program
certificate.issued the person holds its certificate; data carry certificate (the number, the moments, verifyUrl)
user.expired the access of the person ended
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
  }
}

Signature

Every message carries X-Responsiblo-Signature: t=<unix time>,v1=<HMAC-SHA256 of the text t.body with the secret of the webhook, hex>. The secret (whsec_...) is shown once when the webhook is created. Check the signature and the age of t before you trust a message; use X-Responsiblo-Delivery as the key of idempotency.

// 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]);

Delivery and retries

A delivery is an answer 2xx within 10 seconds. Otherwise we try again after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours, then we give up. Redirects are not followed.

20 failed deliveries in a row switch the webhook off until you switch it on again; the messages of the time between wait. The button Test sends a ping; the log of the deliveries is in your administration.

Add the event certificate.issued to a webhook in its settings; a webhook made before version 1.2 does not get it by itself.

Errors

Every error has one shape: status, code, reason and message; a 422 adds errors (field - what is wrong).

{ "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" } }
HTTPreasonWhat to do
400 invalidJson send one JSON object
401 missingToken, invalidToken send a valid key (a revoked and an expired key look the same); the header WWW-Authenticate says Bearer
403 scopeDenied, ipNotAllowed, apiDisabled, partnerInactive, spaceUnavailable, httpsRequired, userLimitReached, seatsExhausted the key may not do this, the API is off for your company, or the program is full
404 userNotFound, notFound no person under this identifier in the program of the key (an anonymized one neither)
404 certificateNotFound, certificatePdfNotReady the person holds no certificate yet, or its PDF is being made - try again after Retry-After
409 identifierTaken the identifier belongs to a person of another program
422 invalidBody, invalidParameter see errors (a field of the body or a parameter of the query - what is wrong)
429 rateLimited wait Retry-After seconds
500 internalError try again later; quote incidentId to our support

For programs and agents

  • Decide by code and reason, never by the text of message; errors is an object field -> what is wrong.
  • Repeat only 429, 500 and certificatePdfNotReady, after Retry-After seconds (otherwise with a growing pause); never repeat another 4xx without changing the call.
  • POST /v1/users is idempotent by identifier (201 the first time, then 200); DELETE answers 204 the first time and 404 afterwards - both are safe to repeat.
  • Deduplicate webhooks by X-Responsiblo-Delivery; the order of the messages is not guaranteed, the state in data decides.

Loan guide

The loan guide is a short course for an applicant of a loan provider: before signing the contract the applicant goes through three lessons, eight practical situations and, when it is on, a quiz, all of it with the numbers of their own offer, and confirms the offer at the end. Every screen lets them ask for an explanation. You send the offer through the API, receive an entry link and a webhook tells you the result.

We activate the loan guide for you by agreement.

Here too the applicant is only your pseudonymous profile of POST /v1/users. The offer is identified by your references (externalApplicationId, offerReference) and the documents only by a link with a SHA-256 fingerprint - never a name, an e-mail, a birth number, an account number or a phone. responsiblo never approves a loan, never downloads or stores the documents, never verifies the identity and issues no certificate for the guide.

  1. You create the profile of the applicant: POST /v1/users with your pseudonym.
  2. You send the offer: POST /v1/users/{identifier}/loan-offers; the answer 201 carries entryUrl.
  3. You hand entryUrl to the applicant over your own authenticated channel. The link holds for 30 days and may be used again; the guide shows the numbers of their offer.
  4. A webhook tells you the end (loanGuide.completed, loanGuide.assistanceRequested and more).
  5. You read the state with GET …/loan-offers/{offerReference} and the record for your file with GET …/evidence. A changed offer = a new offer with supersedes, a withdrawn application = POST …/cancel.

Until it is activated, the operations of the guide answer 404 notFound or 409 loanGuideNotConfigured. The scope write sends and cancels an offer, read reads the state and the evidence.

POST /v1/users/{identifier}/loan-offers

Sends an offer for the profile of the applicant (scope write). The optional header Idempotency-Key has 1 to 255 visible ASCII characters. The example: a loan of CZK 10,000, CZK 10,800 to pay in one payment 30 days after the payout, APR 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"
}
FieldRequiredMeaning
externalApplicationId yes Your number of the application, 1 to 128 characters A-Z a-z 0-9 . _ : -; never an e-mail address.
offerReference yes Your reference of the offer, the same rules as externalApplicationId.
locale yes The language and the country of the guide: cs-CZ.
currency yes The currency: CZK.
principalMinor yes The amount of the loan in hellers, an integer from 1 to 10,000,000,000.
disbursedAmountMinor yes The amount paid out in hellers; it must equal the amount of the loan.
totalPayableMinor yes The total amount payable in hellers; at least the amount of the loan and exactly the sum of the payments.
aprPercent yes The APR in percent as a text ("155.10"), computed and guaranteed by you. The API refuses positive costs with an APR of 0.
interestRate no The interest rate {percent, period}, period = year, month or day.
repayment yes The repayment: singlePayment {amountMinor, due} with a date (kind date) or a number of days from the payout (kind relative, 1 to 365), or installments {schedule: [{date, amountMinor}]} with 1 to 360 instalments in ascending order, none in the past. The type must be the product type set up for your guide.
documents yes 2 to 10 documents {role, reference, title, url, sha256}; the roles the settings of your guide require are covered (by default precontract_information and contract_package). url only HTTPS on a host allowed in the settings of your guide, at most 2,048 characters, no credentials; sha256 = 64 hexadecimal characters declared by you.
validUntil yes The validity of the offer, RFC 3339 with an offset, in the future and at most 7 days ahead.
supersedes no The offerReference of the active offer of the same profile that the new offer replaces.
returnUrl no Optional: the address the page Done sends the applicant back to after the guide. Absolute HTTPS only, at most 2,048 characters, no credentials; we replace the placeholders {offerReference} and {externalApplicationId} with the references of the offer. Without it the return address from the settings of your guide applies.

The same body again (under the same references or the same Idempotency-Key) answers 200 with the existing offer and a fresh entryUrl; another body under them answers 409 offerConflict. A profile has one active offer: another one without supersedes answers 409 activeOfferExists, a wrong supersedes 409 notSupersedable. The settings of your guide (the quiz, the contact) are locked into the offer at that moment.

State, evidence and cancellation

  • GET /v1/users/{identifier}/loan-offers/{offerReference} - the state (scope read): offerStatus (active, expired, superseded, cancelled), guideStatus (created, in_progress, completed), the completed lessons, the practice, the quiz (null when it is off) and the moments of the presentation of the offer, the confirmation and the request for an explanation. Never an answer, a value of the offer or the link. A completion stays when the offer expires later.
  • GET /v1/users/{identifier}/loan-offers/{offerReference}/evidence - the record for your file (scope read): schemaVersion loan-guide-evidence/1, the snapshot of your offer with its fingerprint snapshotSha256, the release of the course with the fingerprints of the lessons, the events in the order of sequence, every answer with all its attempts, the confirmation and limitations - what the record does not prove (presented does not mean read, the identity is asserted by you, the documents by reference only, no certificate, no approval of a loan).
  • POST /v1/users/{identifier}/loan-offers/{offerReference}/cancel - cancels an active offer (scope write), reasonCode = withdrawn_by_provider or application_closed; 200 answers the state, an offer that is not active or whose guide is completed answers 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= is needed only when one offerReference belongs to more applications of the profile (otherwise 409 ambiguousOfferReference).

Webhooks of the guide

The webhook of the program (see Webhooks) receives the events of the guide without a subscription. The signature, the delivery and the retries are those of the other events; data carry identifier, offerReference, externalApplicationId, guideStatus, occurredAt and sequence (the order of the events of one offer) - never the evidence, a value of the offer or the entry link.

EventWhen
loanGuide.completed the applicant went through the guide and confirmed the offer
loanGuide.assistanceRequested the applicant asked for an explanation (call them)
loanGuide.expired the offer passed validUntil
loanGuide.superseded a new offer replaced it (supersedes)
loanGuide.cancelled you cancelled the offer
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
  }
}

Each event reaches one webhook at most once (the key of idempotency = X-Responsiblo-Delivery). A webhook created later does not replay older events, and events older than 28 days are not announced any more.

Retention of the evidence

When the way of an offer ends (a completed, cancelled, expired or superseded offer), the retention period of your guide runs (30 days by default). Then the evidence is deleted: GET …/evidence answers 410 evidenceErased and the state still answers with evidenceErased: true, the references and the moments. An active offer is never deleted. Download the evidence you must keep right after loanGuide.completed.

Errors of the guide

The errors have the shape of the API above. In addition for the guide:

HTTPreasonWhat to do
404 offerNotFound the profile has no such offer (userNotFound = no such profile)
409 offerConflict, activeOfferExists, notSupersedable the references or the Idempotency-Key belong to another body, or the profile has another active offer - send supersedes
409 loanGuideNotConfigured the guide is not activated for your program - write to us
409 ambiguousOfferReference add ?externalApplicationId=
409 notActive the offer is not active or its guide is completed
410 evidenceErased the evidence was deleted after the retention, the state stays
422 invalidOffer errors = {path: code[,code]} with the path in the body (repayment.schedule[2].date, documents[0].url); the codes in the table below
422 invalidBody supersedes, Idempotency-Key or the body of the cancellation
errorsThe codes of the error invalidOffer
required the field is missing
invalidFormat a wrong shape (type, pattern, length, a link without HTTPS or with credentials)
outOfRange outside the allowed range (an amount, the number of documents, instalments or days)
notEqualPrincipal the amount paid out does not equal the amount of the loan
sumMismatch the sum of the payments does not equal the total amount payable
belowPrincipal the total amount payable is lower than the amount of the loan
aprContradiction an APR of 0 with positive costs
typeMismatch the type of the repayment is not the product type set up for your guide
missingRole a document with a role the settings of your guide require is missing
hostNotAllowed the link of a document points to a host the settings of your guide do not allow
notAscending the dates of the instalments are not ascending or repeat
inPast the date of a payment or validUntil is in the past
tooFar validUntil is more than 7 days ahead
unsupported an unsupported value (locale, currency, type, period, kind)
unknownField a field the API does not know
looksLikeEmail a reference looks like an e-mail address

An error never repeats a value you sent. The example: the same offer with a payment of CZK 10,700 instead of CZK 10,800 and a validity of 9 days:

"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"
  }
}

Limits

120 calls a minute per key. After 30 refused keys from one address in ten minutes the address waits 10 minutes.

The log of the calls (no bodies, the identifier as a SHA-256 fingerprint only) is kept 180 days, the delivered and the given up webhook messages 30 days.

Status and contract

  • GET /v1/status - no key, answers {"status":"ok","version":"1.3.2"}
  • GET /openapi - no key, the OpenAPI 3 document of the partner API

Sandbox

A test key rsb_test_... opens your sandbox program with the same course. Persons there end after 7 days; webhooks of the sandbox program are set apart from the production ones.

Changelog

  • 1.3.2 (2026-11) - Every operation of the OpenAPI document has a name and a description, and the operations are sorted into groups. /v1/status and the webhooks report the version 1.3.2. The shapes of the requests and the responses are unchanged.
  • 1.3.1 (2026-10) - Fixes; the endpoints and their responses are unchanged.
  • 1.3.0 (2026-10) - The loan guide: POST /v1/users/{identifier}/loan-offers, the state, the evidence and the cancellation of an offer, the webhooks loanGuide.*, the retention of the evidence. The optional returnUrl of an offer (its own return address).
  • 1.2.0 (2026-10) - GET /v1/users page by page, the certificate of a person (certificate, GET /v1/users/{identifier}/certificate, the event certificate.issued), DELETE /v1/users/{identifier} (anonymization), the identifier at most 64 characters, the retention of the log.
  • 1.1.0 (2026-10) - API keys, POST /v1/users, GET /v1/users/{identifier} with ?include=detail, the entry link, webhooks, one shape of errors, public status and OpenAPI, limits.
  • 1.0.0 (2024) - GET /v1/user/{identifier} with the JWT of a partner key.

Do you want the API for your company? Write to us