Skip to content

QR code and PDF payloads

Each payslip has a Verifiabl reference. The QR code contains this reference, and a lender uses it during verification. There are two methods to make a reference.

Verifiabl-generated. If you omit the reference from registerNonPII, Verifiabl makes one and returns it. The registerAndBuildBarcode endpoint always makes and returns the reference.

Provider-generated. Send a reference to registerNonPII or registerNonPIIBatch. The official Node, .NET and Ruby SDKs generate and send one automatically for single registration. They reuse it for automatic retries. Batch registration always requires a provider reference. Generate and store one yourself when a later call or a process restart must use the same idempotency key.

A Verifiabl reference is 22 base64url characters. It is a 128-bit value with the characters A-Z, a-z, 0-9, - and _, and no padding. A reference from Verifiabl and a reference from a provider have the same format.

Make each reference from 16 random bytes from a CSPRNG. Encode the bytes as base64url with no padding. The result is 22 characters. A reference must have no pattern, and a person cannot calculate it. With 128 bits of entropy, two equal references are not probable. Registration rejects an existing reference if the content is different. Each reference is unique.

  • ✓ Use one Verifiabl reference for each payslip, and send the same reference again after a failure. The reference is your idempotency key. A new reference in a second request makes a second record.
  • ✓ Do not use a reference again for a different payslip. If you send a reference with different data, the API rejects the request with 409 CONFLICT. Verifiabl does not overwrite a record.

Example reference:

Provider-generated Verifiabl reference
K3mXq8Rt2pLz9wQv1AYb_w

V2 is the current barcode format. The QR code contains a Verifiabl scan URL. A phone opens the URL; a lender integration sends the full URL to the verification API without opening it.

Scan URL encoded in the QR
https://v.verifiabl.io/v/<verifiabl_reference>#2.<BASE32>

The Verifiabl reference goes in the path. The encrypted PII goes in the fragment, after the # character. In sandbox, the host is v.sandbox.verifiabl.io.

Put the encrypted PII in the fragment only. A browser does not send the fragment to a server. Thus the encrypted PII stays out of the Verifiabl server logs, and out of the logs of each system between. If you put the encrypted PII in the path or in the query string, these systems record it, and they can keep it for a long time. Do not put the encrypted PII in the path or in the query string.

PartLocationDescription
verifiabl_referencePath, after /v/The Verifiabl reference from the registration response
2Fragment, before the dotProtocol version
encrypted_piiFragment, after the dotBase32-encoded encrypted PII

The official Node, .NET and Ruby SDKs make the scan URL and the Verifiabl QR code. They support SVG and PNG output. On a different platform, make the scan URL in your system. Obey these three rules:

  • ✓ Put the reference in the path, then add #2. and the base32 encrypted PII. Do not put the pipe-delimited payload in the path.
  • ✓ Do not percent-encode the URL. The reference and the base32 encrypted PII use URL-safe characters.
  • ✓ Do not add a space, a line break, or a query string. A QR scanner shows a link only if the full text is a valid URL. If the text has an unsafe character, the phone shows plain text, and the person cannot open the link.

Then make the QR code with a supported QR library.

The official SDKs need no extra package install for PNG output.

Embedding: make the QR code at a high resolution. It must stay readable after you print it. Then scan the QR code on the PDF as a test.

Write the pipe-delimited payload into the XMP metadata of the payslip PDF. The QR code holds the same reference and the same encrypted PII, but as a scan URL. Then the PDF contains the two values in two independent locations.

XMP namespacehttps://verifiabl.io/ns/ (prefix verifiabl)
Propertyverifiabl:payload
Value2|<verifiabl_reference>|<BASE32>

One payslip contains one payload. Write the payload with the tool that makes your PDF: a PDF library or your own code. The XMP packet is XML in the document. Use the namespace and property in the table above.

XMP packet (excerpt)
<rdf:Description rdf:about=""
xmlns:verifiabl="https://verifiabl.io/ns/">
<verifiabl:payload>2|n5waC35dPCoRtMXW5_gJqw|JVSWY3DPO5XXE3DE</verifiabl:payload>
</rdf:Description>

The metadata contains the pipe-delimited payload 2|verifiabl_reference|BASE32. It never contains plaintext PII. The QR code contains the scan URL, which is a different shape: it holds the same reference and the same encrypted PII, but the encrypted PII goes in the fragment. Do not put the pipe-delimited payload in the QR code.