Create an immediate dynamic PIX QR code
Generates an immediate dynamic PIX QR code and persists its conciliation metadata. The plugin sends the JWS host URLs (urlPayloadJson / urlJwk) to JDPI and self-hosts the signed JWS, so the returned QR is end-to-end resolvable; the response carries the resolvable payload URL the EMV embeds. cobv (due-date) and saque/troco variants are not supported.
WHAT indirectId DECIDES HERE IS WHO SERVES THE QR, and it is a decision about hosting rather than about whose charge it is. This participant may serve INDIRECT participants — institutions registered with POST /v1/indirects. Most of them need nothing here: by default a QR raised for one of them is signed with THIS participant’s certificate and its payload is hosted on THIS participant’s domain, which is the ordinary arrangement and the one nearly every institution wants. An institution that has opted into holding its OWN certificate is the exception, and only for it does indirectId change anything: JDPI then signs with that institution’s certificate, the payload URL is built on that institution’s own domain, and the signed document comes back to you to host there. Certificate and domain are ONE decision, never two — the payer’s app validates the signature against the certificate published at the domain that answered, so signing with one party’s certificate while hosting on another’s does not validate.
⚠️ indirectId IS REFUSED 422 PIX-0111 WHILE THIS TENANT’S INDIRECT-PARTICIPANTS FEATURE IS SWITCHED OFF, and the refusal names the setting an operator has to turn on. It is never dropped: a QR minted as if you had sent none would be signed with THIS participant’s certificate and published on THIS participant’s domain, so you would have asked for one institution’s QR and silently received another’s. Send no indirectId and the QR is generated exactly as it always was.
Refusals specific to indirectId — all decided before JDPI is called, so a refused QR is never generated: 422 PIX-0111 when this tenant’s indirect-participants feature is off (the value is refused rather than parsed, so none of the others can be reached); 404 PIX-0095 for an id that addresses no institution registered in this tenant (a malformed UUID lands here too — it can address none); 422 PIX-0100 when the institution it names is not ACTIVE; 422 PIX-0113 when that institution’s registered public base URL names a host a payer’s app cannot resolve; 422 PIX-0112 when the composed payload URL exceeds the 77 characters BACEN allows — the path this participant is configured with spends most of that budget, so an institution’s hostname must be chosen against the remaining allowance BEFORE it is registered, not after.
When indirectId names an indirect that hosts its OWN certificate, the signed JWS comes back in payloadJws and the plugin does NOT store it — the indirect hosts it at payloadUrl on its own infrastructure, so THIS RESPONSE IS THE ONLY DELIVERY OF IT. If the response never reaches you (client timeout, connection reset, proxy error) the charge nevertheless exists at JDPI, and re-sending the same recipientConciliationId is refused as a duplicate (PIX-0065). Recover it, do not re-create it: call GET /v1/qrcodes/list with qrCodeType 12 over the registration window, match your own recipientConciliationId to read its documentId, then call PUT /v1/qrcodes/dynamic/ with the SAME indirectId — the update re-signs the charge and returns a fresh payloadJws (JDPI §8.3.5 returns payloadJws on every update). The update mints a NEW payloadUrl and a regenerated EMV payload, so it REPLACES the lost QR rather than reproducing it; host the new payloadJws at the new payloadUrl and distribute the new qrCode.
Hosting the payload is not the whole obligation: an institution serving its own domain must ALSO publish, at that domain, the key set the payer’s app validates the signature against. It cannot produce that key set itself — JDPI holds the certificate and does the signing — so read it with GET /v1/indirects//jwks and serve those bytes verbatim, re-reading whenever the certificate is rotated. A payload served without a matching key set fails validation at the payer, silently: the QR scans, the app fetches the document, and the payment does not go through.
Which of this deployment’s direct participants acts is decided by ispb, by exactly the rule an order’s payerIspb follows: this deployment may act as several direct participants, each with its own customers and its own JDPI credential, and naming none is answerable only while there is one answer. Omit it while this deployment acts as a single participant; once it acts as several, omitting it is 422 PIX-0127 and naming one it is not is 422 PIX-0128. The published payloadUrl and its JWKS location carry THAT participant’s ISPB, so a QR minted as the wrong participant sends every payer’s PSP to a key set that cannot validate its signature — and by then the QR is already in the wild. An indirect’s QR is minted, signed and published by the participant recorded at that indirect’s registration - the one direct participant it mounts on, which is NOT necessarily this deployment’s default one - so supplying indirectId together with any other ispb, the default one included, is 422 PIX-0102; leaving ispb blank on an indirect request resolves to that same recorded participant rather than to the default.
Authorizations
JWT bearer token issued by the identity provider.
Body
The CRM account id of the recipient (sources name + city).
"acc-123"
Amount in centavos (an integer).
10050
The recipient PIX key the dynamic QR pays into.
"recipient@bank.com"
Conciliation id (idConciliacaoRecebedor); §8.3.2 mandatory; 26..35 alphanumeric ([a-zA-Z0-9]); dedup gate.
"JDPI2020010300000000000000000000001"
Optional additional-data entries (dadosAdicionais).
QR expiration in seconds (0 = JDPI default).
3600
Optional identifier (UUID) of an indirect participant registered here. When that institution hosts its OWN dynamic-QR certificate, JDPI signs with its certificate, payloadUrl is built on its domain, and payloadJws is returned for it to host; otherwise the QR is signed and hosted by the direct participant exactly as if this were omitted. Omit for a direct QR. Validated server-side: unknown or inactive is rejected. Refused 422 PIX-0111, naming the setting to enable, while this tenant's indirect-participants feature is off: routing you supply is never silently dropped.
"3f2504e0-4f89-41d3-9a0c-0305e82c3301"
The ISPB of the direct participant that mints this QR. This deployment may act as SEVERAL direct SPI participants - one ISPB each, each with its own customers and its own JDPI credential - and this field is the only thing on the request that says which of them acts. OPTIONAL while it acts as a single participant: omit it and that one acts. REQUIRED once it acts as several - omitted is 422 PIX-0127, and an ISPB this deployment does not act as is 422 PIX-0128. It is ROUTING DATA you supply and guarantee, exactly like payerIspb on a transaction: never a credential, never read from a header or a path, and it never widens what your token can reach. The published payloadUrl and its JWKS location are built under this participant's ISPB, so a QR minted as the wrong one points every payer's PSP at a key set that cannot validate its signature. When indirectId is supplied this must be blank or the participant recorded at that indirect's registration, which is NOT necessarily this deployment's default one; naming any other is 422 PIX-0102. Send it as an absent key, not an empty string; an empty value is refused 400 PIX-0061.
^[0-9]{8}$"12345678"
Optional payer block.
Recipient postal code (cep).
"01310100"
Response
Created
The generated EMV QR-code payload (base64-decoded, ready to render).
"00020126..."
The JDPI charge GUID (idDocumento) addressing the update leg (dynamic only).
"52c43361-caa1-4ddb-9152-708426a25db3"
The signed JWS payload, returned ONLY when the QR was generated under an indirect participant's own certificate — that indirect hosts it at payloadUrl on its own infrastructure. Absent on the direct path, where the plugin self-hosts it. It is returned ONCE and never stored: if this response is lost, do NOT re-create (the same recipientConciliationId is refused as a duplicate) — read the charge's documentId from GET /v1/qrcodes/list and re-sign it via PUT /v1/qrcodes/dynamic/{documentId} with the same indirectId, which returns a fresh payloadJws on a fresh payloadUrl.
"eyJhbGciOiJFUzI1NiJ9.eyJyZXYiOjB9.sig"
The resolvable JWS host URL the dynamic QR embeds (urlPayloadJson; schema-less; dynamic only).
"pix.example.com/qr/cob/fzqRwuXYSweWofLD1OX2Bw"

