> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# How routing works

> How JD Courier decides which engine receives each SPB and Pix message, and what happens to a message that it cannot route or deliver.

The Courier decides one thing for each message that JD sends to your institution: which engine receives it. This page explains the ownership map, the routing rules of each rail, and the retention of the messages that the Courier cannot route or deliver.

## The ownership map

***

The ownership map is a list of keys. Each key has one owner engine. An operator creates and changes the map through the [ownership API](/en/reference/interfaces/jd-courier/assign-a-key-to-an-engine). The Courier refuses a second owner for a key with `409 JDC-0102`. To change the owner, the operator [moves the key](/en/reference/interfaces/jd-courier/move-a-key-to-another-engine).

The map accepts seven kinds of key:

| Key kind | What it identifies | Used by inbound routing |
| - | - | - |
| `ACCOUNT` | An account, as branch and account number. A payment account has no branch. | Yes, on SPB and Pix |
| `DOCUMENT` | A CPF or a CNPJ. | Yes, on Pix Automático, for the CNPJ of the charger |
| `PIX_RECURRENCE_ID` | A Pix Automático recurrence. | Yes, on Pix Automático |
| `PIX_KEY_EMAIL` | An email Pix key. | No |
| `PIX_KEY_PHONE` | A phone Pix key, in E.164 format. | No |
| `PIX_KEY_RANDOM` | A random Pix key. | No |
| `PAYMENT_ID` | A payment identifier. | No |

The kinds that inbound routing does not use are available to the engines through the [ownership lookup](/en/reference/interfaces/jd-courier/resolve-which-engine-owns-a-key). An engine uses the lookup to find out if another engine owns the destination of a payment.

The Courier normalizes each key value. For example, it removes the punctuation from a CPF and the leading zeros from a branch. Send the value as you hold it.

Every change to the map writes an entry in the audit history of the key, in the same transaction. The entry records who made the change, when, the previous owner, and the new owner. A move also records its reason. You can read the history of a key after its removal, through the [audit lookup by key](/en/reference/interfaces/jd-courier/ownership-history-for-one-key-addressed-by-the-key).

## Routing on the SPB rail

***

The `spb-consumer` role reads the SPB messages that JD holds for your institution. The Courier stores each message before it decides the route. Then it applies these rules, in order:

1. **Send journal.** When the control number (`NumCtrlIF`) of the message matches a send in the [send journal](#sends-to-jd-and-the-send-journal), the message goes to the engine that made the send. This rule routes the replies to messages that an engine sent.
2. **Ownership map.** The Courier reads the credited account of the message: branch and account, or the payment account. When the map has an owner for that account, the message goes to the owner.
3. **Delivery mode.** When the map has no owner, the Courier reads the [delivery mode](#delivery-modes) declared for the message code. This rule never applies to the money codes `STR0008`, `STR0008R1`, `STR0008R2`, `STR0010`, `STR0010R1`, and `STR0010R2`.
4. **Retention.** When no rule decides, the Courier [retains](#retained-messages) the message.

The engine must be enabled. When rule 1 or rule 2 names a disabled engine, the Courier retains the message with the reason `DELIVERY_FAILED`.

The Courier does not push SPB messages to the engines. Each engine asks the Courier for its messages through the same SOAP interface it uses with JD. The Courier answers with the oldest message that waits for that engine. For details, see [Connecting an engine](/en/interfaces/jd-courier/jd-courier-engine-integration).

### Delivery modes

A delivery mode applies to one SPB message code. An operator [declares it](/en/reference/interfaces/jd-courier/declare-the-delivery-mode-for-one-message-code) with a reason. There are two modes:

* `ALL_ENGINES`: the message goes to every enabled engine.
* `REFUSE`: the message goes to no engine. The Courier keeps it, with the state `REFUSED`.

A code without a declaration follows the default: one owner. The Courier refuses a declaration for a money code with `422 JDC-0110`. A revoked declaration stays readable as history. The Pix rail accepts no declaration.

### Redelivery

An operator can [serve an SPB message again](/en/reference/interfaces/jd-courier/reopen-the-delivery-of-a-message-to-an-engine) to one of the engines that the message was routed to. The Courier does not ask JD again. The next request of the engine receives the stored message, with its original sequence number. Your operator gives a reason, and the Courier records it.

### Bypass

A bypass is the state where one engine connects to JD directly again, outside the Courier. An operator declares a bypass on the SPB rail with the engine and a reason.

While a bypass is active, the Courier does not read from JD on that rail. It also does not route or re-check SPB messages. A reconciliation cycle that runs during a bypass lists the suspended guarantees. At most one engine can be in bypass on a rail. The Pix rail has no bypass.

## Routing on the Pix rail

***

JD sends the inbound Pix calls of your institution to the address that the `pix-ingress` role serves. The Courier decides the owner during the call, delivers the call to the engine, and relays the answer of the engine to JD.

JD makes two kinds of call:

* **Questions.** JD waits for an answer before it continues: account validation, the Pix Automático debit block, and the authorization and schedule validations. The Courier does not retain a question.
* **Messages.** JD reports a fact: cash-in, refund (devolução), and the Pix Automático registrations, settlements, and events. The Courier can retain a message.

### Which key routes each call

| JD call | The owner is the engine that owns |
| - | - |
| Account validation, cash-in, refund | The account of the payee |
| Pix Automático debit block | The account in the block |
| Pix Automático debit and debit reversal | No key: the call goes to the engine that received the debit block |
| Authorization payer registration, and its event | The account of the payer |
| Authorization recipient registration, and its event | The CNPJ of the charger |
| Authorization validation, cancellation, and status events | The account of the payer, when the payer ISPB is one of yours. The CNPJ of the charger, when the payer ISPB is not one of yours. |
| Schedule validation, registration, cancellation, and their registration events | The recurrence |
| Schedule status event | The account of the payee |
| Schedule cancellation status event | No key: the call goes to the engine that holds the schedule |

Your ISPBs are the participant ISPBs that the operator registers on the engines.

The Pix Automático calls that follow an earlier leg need a record of that leg. The Courier records the earlier legs that it delivers. For the payments in progress before the Courier receives Pix, each engine declares its legs. See [Connecting an engine](/en/interfaces/jd-courier/jd-courier-engine-integration).

### What JD receives

| Situation | Message | Question |
| - | - | - |
| The owner engine takes the call | The answer of the engine, as it came. The Courier stores it and answers each resend of JD with it. | The answer of the engine, as it came. |
| The Courier stores the call but cannot route or deliver it | `503`. The Courier retains the message. | — |

When the engine answers a message with a `5xx`, `408`, or `429` status, the Courier relays that answer to JD and retains the message. The next resend of JD reaches the engine again. When the engine answers with a `3xx`, `401`, or `403` status, or does not answer, JD receives `503` and the Courier retains the message.

## Retained messages

***

A retained message stays in the Courier database with its reason. The Courier does not credit it, return it to BACEN, or delete it. Your operator lists the retained messages, oldest first, through [the retained API](/en/reference/interfaces/jd-courier/list-retained-messages). The list shows the reason and the times. It does not show the content of the message.

| Reason | Rail | Meaning | Re-checked |
| - | - | - | - |
| `ACCOUNT_UNASSIGNED` | SPB, Pix | The Courier read the key of the message, and no engine owns it. On Pix, also: the earlier leg of the message has no record. | Yes |
| `UNRECOGNIZED_TYPE` | SPB | The message has no key that the Courier reads, and its code has no delivery mode. | Yes |
| `OWNERSHIP_DECISION_UNAVAILABLE` | Pix | The Courier could not read the data for the decision. Also used when an earlier attempt sent the message to an engine that is no longer the owner. | Yes |
| `DELIVERY_FAILED` | SPB, Pix | The delivery to the engine failed. | Yes |
| `CLASSIFICATION_FAILED` | SPB, Pix | The Courier could not classify the message. | No |

### How a retained message leaves

The Courier re-checks each retained message with a routing or delivery cause, at most once a minute. When the cause clears, the message leaves by itself. For example, an operator assigns the account, or enables the owner engine again. On Pix, a resend of JD also runs the decision again.

An operator can also [request a re-evaluation](/en/reference/interfaces/jd-courier/run-a-retained-message-s-routing-decision-again) with a reason. The Courier records who asked, when, and why, and re-checks the message first. The re-evaluation runs the same routing rules as a new message. The operator never chooses the engine. The Courier refuses a re-evaluation for the reason `CLASSIFICATION_FAILED` with `422 JDC-0204`.

When the Courier releases a Pix message, JD is not in the call. The Courier stores the answer of the engine and gives it to JD at the next resend.

## Sends to JD and the send journal

***

Engines send their SPB messages to JD through the `spb-sender` role. The Courier writes each send in the send journal before the send leaves. Then it sends the message to JD once and relays the answer of JD to the engine. The Courier never sends a message again by itself.

The send journal records one of these outcomes for each send:

| Outcome | Meaning |
| - | - |
| `DETERMINED` | JD answered with a verdict. |
| `INDETERMINATE` | The message left, and no verdict came back. It possibly reached JD. |
| `RESOLVED` | A later answer of JD settled an indeterminate send. |
| `NOT_SENT` | The message did not leave the Courier. |

The Courier accepts each control number once for each tenant. A send with the outcome `NOT_SENT` does not count. A second send of the same control number does not reach JD.

An indeterminate send gets its answer when the engine queries JD about it through the Courier. To handle the indeterminate sends that remain, see [Daily operations](/en/interfaces/jd-courier/jd-courier-operations).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.