> For the complete documentation index, see [llms.txt](https://apidocs.juicefin.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://apidocs.juicefin.com/apis/transactions/decoding-an-iso-8583-payload.md).

# Decoding an ISO 8583 Payload

> **Goal:** Understand the fixed‑position pieces that make up the ASCII string we receive in `ISOFullMessage`, so you can split it by eye or with any language / tool.

***

## 1. High‑level Structure

```
┌──────────────────────────────────────────────────────────────┐
│ Transport / Host header        (variable, host‑specific)     │
│ ──────────────────────────────────────────────────────────── │
│ MTI           4  n                                            │
│ Primary bitmap 16  n  (64 bits → 16 hex characters)          │
│ Secondary bitmap 16  n  (present only if bit 1 = 1)          │
│ Data elements  …   (1‑128, in ascending order)               │
└──────────────────────────────────────────────────────────────┘
```

* **All characters are ASCII.**
* Numeric fields (`n`) are right‑justified, **zero‑padded**.
* Alphanumeric fields (`ans`) are left‑justified, **space‑padded**.
* Variable‑length fields begin with a numeric **length prefix**:
  * `LLVAR` → 2 digits (00‑99)
  * `LLLVAR` → 3 digits (000‑999)

***

## 2. Example in the Wild

Below is the **authorization** message you saw (line‑wrapped & spaced):

```
ISO0260000700 | 0120 | B23AC4112EE1801C
0000000214000100 | 0000000000000000 | 0285
0724181349 | 863303 | 141300 | 0724 | 0724
554105 | 2C0000000006 | 12345621543464******6993=0000427704382626
185503 | 0000010003        | 127298000000000
EXXON UPPY'S #68 #2009CENTREVILLE  VA US
0100724141353840 | 0160000000
… (continues)
```

### What those chunks are

| Segment            | Meaning                                                                                                                                   | Why the spacing?                                                                                                    |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `ISO0260000700`    | **Transport header** – prepended by the host to carry length, protocol version, routing info. Its size (12–20 bytes) is *vendor‑defined*. | Not part of ISO 8583 proper. Discard before parsing.                                                                |
| `0120`             | **MTI** – `0 120` = Authorization Advice.                                                                                                 | Always 4 numeric chars.                                                                                             |
| `B23AC4112EE1801C` | **Primary bitmap** (16 hex chars = 64 bits). Bit 1 is set (`B = 1011`), so a secondary bitmap follows.                                    | Every 4 bits are packed into one hex char—no delimiter.                                                             |
| `0000000214000100` | **Secondary bitmap** (also 16 hex).                                                                                                       | Present only because bit 1 in the primary bitmap = 1.                                                               |
| Remaining blocks   | **Data elements** in ascending order (2, 3, 4, … ). Each occupies exactly its specified length, *or* `LL/LLL` prefix + value.             | Padding (zeros / spaces) makes every fixed field keep its place so downstream systems can slice without delimiters. |

***

## 3. Bitmap → Which Fields Follow?

1. Convert each hex char to binary. *Example:* `B23A…` → `1011 0010 0011 1010 …`
2. Number bits **1‑64** (or 1‑128).
3. If a bit = 1, its corresponding field *immediately follows* the bitmap(s).
4. Move through the message **in ascending field order**, reading:

| Field #                        | Format    | Length   | Notes                                          |
| ------------------------------ | --------- | -------- | ---------------------------------------------- |
| **2 – PAN**                    | `LLVAR n` | up to 19 | `LL` tells you how many digits follow.         |
| **3 – Processing code**        | `n`       | 6        | Always `000000` for POS sale in our messages.  |
| **4 – Amount, Txn**            | `n`       | 12       | Right‑padded zeros: `00000000285` = $2.85      |
| **11 – STAN**                  | `n`       | 6        | `185503` in the sample.                        |
| **37 – Retrieval Ref # (RRN)** | `an`      | 12       | `724181349863` – used to link auth ↔ purchase. |
| **41 – Terminal ID**           | `ans`     | 8        | `00010003` (space‑padded if shorter).          |
| **…**                          |           |          |                                                |

*(The complete ISO 8583 spec defines > 120 fields. Only the ones lit by the bitmap are present.)*

***

## 4. Reading Variable‑length Fields

```
PAN (Field 2)  =  16  543464******6993
                 ──┘ └─────────────────
                 length indicator  (2 chars)
```

* If the bitmap says Field 2 exists, **take the next 2 chars**, convert to an int (`16`), then read *exactly* that many chars for the PAN.
* Immediately after that, continue with the next field (Field 3).

***

## 5. Padding Rules Cheat‑Sheet

| Format                                | Justify   | Pad with                              | Example                                          |
| ------------------------------------- | --------- | ------------------------------------- | ------------------------------------------------ |
| `n` (numeric)                         | **right** | `0`                                   | `00000000285`                                    |
| `an`, `ans` (alpha / alnum / special) | **left**  | space (`0x20`)                        | `00010003··` → becomes `00010003 <space><space>` |
| Track / discretionary                 | fixed     | `F` or `=` etc. as per card standards | `543464******6993=...`                           |

> *Tip:* When debugging, replace `0x20` with `·` so you can *see* trailing spaces.

***

## 6. Putting It All Together (Walk‑through)

1. **Strip transport header** (`ISO0260000700`).
2. **Read MTI** (`0120`).
3. **Read Primary bitmap** (16 hex).
4. Because bit 1 = 1, read **Secondary bitmap** (another 16 hex).
5. **Iterate fields**:
   * bit 2 = 1 → Field 2 (LLVAR) → read length *LL* → read PAN.
   * bit 3 = 1 → Field 3 (6 n) → read 6 chars.
   * … continue until all `1` bits are consumed.
6. You should land **exactly on the last byte** of the message. Extras mean parsing error.

***

## 7. Where the Retrieval Reference Number Hides

* Field 37 (RRN) always shows up **after** Field 35/36 (Track2/Track3) for our host.
* Because we *never* carry field 70+ in auth/purchase, the RRN is usually < halfway down the message.
* Example auth vs. purchase pair:

```
Auth  – … 185503 | **724181349863** | 0000010003 …
Purchase – … 583719 | **724181349863** | 895229592889 …
```

**Same RRN → same transaction lifecycle**.

***

## 8. Appendix – Field Directory (Common in Our Webhooks)

| Field | Length         | Format | Meaning                          |
| ----- | -------------- | ------ | -------------------------------- |
| 2     | LLVAR (≤ 19)   | n      | Primary account number (PAN)     |
| 3     | 6              | n      | Processing code                  |
| 4     | 12             | n      | Amount, transaction              |
| 11    | 6              | n      | System trace audit number (STAN) |
| 12    | 6              | n      | Local Txn time (hhmmss)          |
| 13    | 4              | n      | Local Txn date (MMDD)            |
| 37    | 12             | an     | Retrieval reference number (RRN) |
| 41    | 8              | ans    | Terminal ID                      |
| 42    | 15             | ans    | Merchant ID (sometimes blank)    |
| 43    | 40             | ans    | Card acceptor name / location    |
| 55    | LLLVAR (≤ 999) | b      | EMV data (if e‑com / chip)       |

*(Fields differ per processor; consult the host spec if something new appears.)*
