This page covers provisioning. Indirect participants explains what a hosted participation is, how an inbound credit reaches one, how its lifecycle behaves, and every refusal it can answer.
Step 7: the delivery-secret encryption key
Why this step exists. When you register an indirect participant, you supply a delivery secret. The plugin signs every notice it sends to that institution’s endpoint with it. It is how the institution knows the notice really came from you. That secret is stored encrypted, and the key that encrypts it does not come from the database. It comes from outside. If the key is not configured, every registration that carries a secret fails. This is not an edge case. It is the whole write surface of the indirect flow.POST. That is the whole recovery.
This
409 means “provision it”, not “try again later”. The rail looked for the key and found that it does not exist. Only an operator can add it. A repeat of the call without that change fails the same way. That is why the code is a 409 and says nothing about a retry.Its sibling is 503 PIX-0123, “Indirect delivery key source unavailable”. You get it when the rail could not read the key, because the custody backend refused or did not answer. The rail then does not know that the key does not exist, because the read did not complete. The response names the dependency that failed, and a retry is the right action. Both codes refuse the registration and store nothing. The pair lets you tell an incomplete setup from an outage.
The format: exactly 64 hex characters. It is an AES-256 key (32 bytes), hex-encoded. That is 64 hex characters, not 63 and not 65.
An absent, blank, or malformed value all produce the same
409 PIX-0107. There is no default and no degradation to storing the secret in the clear. That is deliberate: a silent default here would store customer secrets encrypted with a key everybody knows.409 PIX-0107 to 201.
Step 8: declare that this tenant hosts indirect participants
Setplugin-br-pix-jd.indirects/enabled to true.
204 when it accepts the value. The value is a JSON boolean, without quotes: {"value":"true"} answers 400.
The management API works with the posture off, so you can register participants before you enable it. The posture gates the money paths. Before you register anyone shows what each half does.
The read fails closed. When a money path “goes back to direct behavior” and nobody changed the key, this is the cause. Look at the systemplane.
Step 9: register an indirect participant
One call does the whole assembly. It checks the ISPB, creates the@pi_{ispb} settlement account in Midaz, and marks the participation active.
A
201 means that the participation is ready to use. The status is always ACTIVE. You do not need to poll.
Indirect participants has the refusals, the lifecycle actions, and how to read the registry back.
Step 10: fund the position
The registration creates the@pi_{ispb} account empty. Inbound Pix credits it, but an outbound payment needs balance first. Without funds, every payment that leaves through that indirect participant fails for insufficient balance. You make the initial load. It mirrors the arrangement: at JD you administer that institution’s limit, and in your ledger you load its position.
The mechanics are the same as the funding step of Setting up the rail. Post a Midaz transaction from @external/BRL, with the same variables as that page. Only the destination changes, to the piAccountAlias from the registration.
close with 409 PIX-0096 while the @pi account holds funds, available or on hold, and names the cause. Bring the position to zero before you close. A funded position keeps the participation open until you do.
How to check. Read the account’s balance back in Midaz. The surest check is behavior: an outbound payment through the indirect participant stops its refusals for insufficient balance.
Return a Pix that an indirect participant received
A Pix for a customer of an indirect participant lands on that participant’s@pi_{ispb} position. To return it, send POST /v1/refunds with the indirectId of that participant. The devolução then debits that position.
The plugin refuses the devolução with 422 PIX-0135 in three cases, and moves no money:
- the original Pix landed on an indirect participant’s position, and the refund has no
indirectId. - the refund names another indirect participant.
- the original Pix landed on a direct account, and the refund has an
indirectId.
indirectId passes the same checks as on a payment order. The hosting posture must be on, and the participation must be ACTIVE.
The systemplane keys of the indirects namespace
There are five keys, all in plugin-br-pix-jd.indirects, and all of them always exist. The three delivery and resolution keys take effect only when enabled is true, because they tune the money paths. validate_ispb_on_jd is the exception. It gates a step of registration, which works while enabled is still false.
204 when it accepts a value and 400 when the validator refuses it. Booleans and integers go without quotes. A value outside the range answers 400. The plugin does not clamp it.
The two steps that can stop the indirect flow on their own are not in this namespace. Identity is the systemplane key
tenancy/jd_integration_binding. Without it, every payment fails with 409 PIX-0092. The encryption key comes from a deployment variable or a secret store. Without it, every registration fails with 409 PIX-0107.
