# EDI to JSON Parser - X12 & EDIFACT (850/810/856/997) (`nibble/edi-to-json`) Actor

Parse B2B EDI interchanges (X12 and EDIFACT) into clean structured JSON with optional structural validation. Purchase orders, invoices, ASNs and acknowledgments — no mapping setup.

- **URL**: https://apify.com/nibble/edi-to-json.md
- **Developed by:** [Simon Fletcher](https://apify.com/nibble) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 transaction parseds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

**EDI to JSON** turns raw **B2B EDI interchanges** — both **ANSI ASC X12** and **UN/EDIFACT** — into clean, structured, agent-ready **JSON**. Drop in a purchase order, invoice, ASN or acknowledgment and get back typed fields (parties, line items, dates, amounts), the full segment tree, and an optional **structural validation** report. No mapping project, no translator license, no onboarding.

### What does EDI to JSON do?

It parses a single EDI interchange into one structured JSON record. It supports the core **commerce transaction sets**:

- **X12**: `850` Purchase Order, `810` Invoice, `856` Advance Ship Notice (ASN), `997` Functional Acknowledgment
- **EDIFACT**: `ORDERS` (purchase order), `INVOIC` (invoice)

For each interchange it returns the **interchange envelope** (sender, receiver, control number, date/time, standard/version), a list of **transaction sets** — each with a typed `parsed` summary *and* the raw `segments` list — plus a **validation** block that checks envelope balance, ST/SE and UNH/UNT segment counts, and control-number matching, and returns an error list. You can send EDI by URL, by uploaded file, or inline as text — ideal for **data pipelines and AI agents** calling it over the Apify API/MCP. Runs on the Apify platform with API access, scheduling, integrations and monitoring built in.

> **Scope & safety:** this Actor handles **commerce EDI only**. Healthcare / HIPAA X12 sets (`837`, `835`, `270`, `271`, `276`, `277`, `278`, `834`, `275`) carry PHI and are **refused** — their contents are never parsed or emitted. It operates only on data you supply; it does no scraping, requires no login, and harvests no personal data.

### Why use EDI to JSON?

- **Skip the EDI translator.** Traditional EDI software (Cleo, SPS Commerce, TrueCommerce, Stedi) means license fees, setup projects and per-partner mapping. This is pay-per-file parsing you can call in one HTTP request.
- **Agent- and pipeline-friendly output.** Flat, typed JSON — no HTML, no nested junk — that an LLM or an ETL job can consume directly.
- **Catch bad interchanges early.** Structural validation flags miscounted segments, unbalanced envelopes and mismatched control numbers before they break a downstream import.
- **Both standards, one Actor.** X12 and EDIFACT in a single call, with automatic format detection and separator handling (including EDIFACT `UNA` service-string advice and release characters).

### How to use EDI to JSON

1. Open the Actor and go to the **Input** tab.
2. Provide your EDI one of three ways: paste it into **Inline EDI text**, add public **EDI URLs**, or upload files and pass their **key-value store keys**.
3. Leave **Structural validation** on (default) to get an error report, or turn it off to parse only.
4. Click **Start**. Each interchange becomes one row in the **Output** dataset.
5. Download the results as **JSON, CSV, Excel or HTML**, or read them over the API/MCP.

### Input

| Field | Type | Description |
|-------|------|-------------|
| `ediText` | array of strings | Raw EDI interchanges passed inline (X12 or EDIFACT). Best for API/agent callers. |
| `ediUrls` | array of URLs | Public URLs of EDI files to download (with retries) and parse. |
| `keyValueStoreKeys` | array of strings | Keys in the run's key-value store holding EDI bytes — how uploaded files are passed. |
| `validate` | boolean | Run structural validation and return an error list. Default `true`. |

Example input:

```json
{
  "ediText": [
    "ISA*00*          *00*          *ZZ*ACMEBUYER      *ZZ*SUPPLYCO       *240115*1200*U*00401*000000001*0*P*>~GS*PO*ACMEBUYER*SUPPLYCO*20240115*1200*1*X*004010~ST*850*0001~BEG*00*NE*PO10001**20240115~N1*BY*ACME CORP*92*ACME01~PO1*1*10*EA*9.99*PE*BP*WIDGET-1~CTT*1~SE*6*0001~GE*1*1~IEA*1*000000001~"
  ],
  "validate": true
}
````

### Output

One dataset item per interchange. You can download the dataset in various formats such as JSON, HTML, CSV, or Excel. A simplified X12 850 result:

```json
{
  "source": "ediText[0]",
  "status": "ok",
  "format": "X12",
  "transactionCount": 1,
  "interchange": {
    "sender": "ACMEBUYER",
    "receiver": "SUPPLYCO",
    "controlNumber": "000000001",
    "date": "240115",
    "time": "1200",
    "standard": "X12 00401"
  },
  "transactionSets": [
    {
      "type": "850",
      "name": "Purchase Order",
      "controlNumber": "0001",
      "parsed": {
        "purchaseOrderNumber": "PO10001",
        "date": "20240115",
        "parties": [{ "entityCode": "BY", "name": "ACME CORP", "idQualifier": "92", "id": "ACME01" }],
        "lineItems": [
          { "lineNumber": "1", "quantity": "10", "unit": "EA", "unitPrice": "9.99", "productId": "WIDGET-1" }
        ],
        "totalLineItems": "1"
      },
      "segments": [{ "tag": "BEG", "elements": ["00", "NE", "PO10001", "", "20240115"] }]
    }
  ],
  "guardrail": { "refused": false, "skippedSets": [], "reason": null },
  "validation": { "checked": true, "valid": true, "errorCount": 0, "errors": [] },
  "meta": { "elementSeparator": "*", "componentSeparator": ">", "segmentTerminator": "~", "segmentCount": 12, "functionalGroups": 1 }
}
```

#### Output fields

| Field | Description |
|-------|-------------|
| `source` | The input reference (URL, key, or inline label). |
| `status` | `ok` if ≥1 in-scope transaction set parsed; `error` otherwise. |
| `format` | `X12`, `EDIFACT`, or `null`. |
| `interchange` | Envelope: sender, receiver, control number, date/time, standard. |
| `transactionSets[]` | Parsed transaction sets: `type`, `name`, `controlNumber`, typed `parsed` summary, raw `segments`. |
| `transactionCount` | Number of in-scope transaction sets parsed (the billable unit). |
| `guardrail` | Healthcare/PHI refusal report (`refused`, `skippedSets`, `reason`). |
| `validation` | `checked`, `valid`, `errorCount`, and an `errors[]` list ({level, code, message}). |
| `meta` | Separators used, segment count, functional-group count. |

### Pricing

This Actor is billed **pay-per-event**: one charge per **successfully parsed interchange** (a non-empty result). Files that are unrecognized, empty, or refused by the healthcare/PHI guardrail are returned as error rows and are **never charged**. Parsing is pure in-container compute (no proxy, no external calls), so runs are fast and cheap; batching many interchanges into one run amortizes startup cost further. See the run's Output and the platform's usage view for exact figures.

### Tips and advanced options

- **Batch** many interchanges in a single run (multiple `ediText` entries or URLs) to minimize per-run overhead.
- Set a **max-charge limit** on the run; the Actor stops before doing further unbilled work once the cap is reached.
- Turn **`validate` off** if you only need the parsed data and want to skip the structural report.
- EDIFACT with a custom `UNA` service-string advice (non-default separators, release character) is handled automatically.

### FAQ, disclaimers and support

- **Which EDI versions?** X12 004010-era commerce sets (850/810/856/997) and EDIFACT D.96A-style ORDERS/INVOIC are the tested v1 scope; other versions of the same sets generally parse at the envelope/segment level.
- **Does it handle healthcare EDI (837/835/270…)?** No — by design. Those carry PHI and are refused; their contents are never parsed or emitted.
- **Is any data stored or sent anywhere?** No. It only processes the EDI you supply and writes the JSON result to your dataset. No scraping, no auth, no personal-data harvesting.
- **Found an issue or need another transaction set?** Use the **Issues** tab — custom sets (e.g. 855, 940, DESADV) can be added on request.

# Actor input Schema

## `ediText` (type: `array`):

Raw EDI interchange strings passed inline (X12 or EDIFACT) — convenient for API or AI-agent callers that send the data directly instead of by URL. Each string is parsed into one structured record.

## `ediUrls` (type: `array`):

Public URLs of EDI files to parse. Each is downloaded (with retries) and parsed to structured JSON.

## `keyValueStoreKeys` (type: `array`):

Keys in this run's default key-value store that hold EDI bytes. This is how files uploaded via the Console form are passed to the Actor.

## `validate` (type: `boolean`):

Run segment/element structural validation (envelope balance, ST/SE and UNH/UNT segment counts, control-number matching) and return a per-interchange error list. Turn off to skip validation and only parse.

## Actor input object example

```json
{
  "ediText": [
    "ISA*00*          *00*          *ZZ*ACMEBUYER      *ZZ*SUPPLYCO       *240115*1200*U*00401*000000001*0*P*>~GS*PO*ACMEBUYER*SUPPLYCO*20240115*1200*1*X*004010~ST*850*0001~BEG*00*NE*PO10001**20240115~N1*BY*ACME CORP*92*ACME01~PO1*1*10*EA*9.99*PE*BP*WIDGET-1~CTT*1~SE*6*0001~GE*1*1~IEA*1*000000001~"
  ],
  "validate": true
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "ediText": [
        "ISA*00*          *00*          *ZZ*ACMEBUYER      *ZZ*SUPPLYCO       *240115*1200*U*00401*000000001*0*P*>~GS*PO*ACMEBUYER*SUPPLYCO*20240115*1200*1*X*004010~ST*850*0001~BEG*00*NE*PO10001**20240115~N1*BY*ACME CORP*92*ACME01~PO1*1*10*EA*9.99*PE*BP*WIDGET-1~CTT*1~SE*6*0001~GE*1*1~IEA*1*000000001~"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("nibble/edi-to-json").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "ediText": ["ISA*00*          *00*          *ZZ*ACMEBUYER      *ZZ*SUPPLYCO       *240115*1200*U*00401*000000001*0*P*>~GS*PO*ACMEBUYER*SUPPLYCO*20240115*1200*1*X*004010~ST*850*0001~BEG*00*NE*PO10001**20240115~N1*BY*ACME CORP*92*ACME01~PO1*1*10*EA*9.99*PE*BP*WIDGET-1~CTT*1~SE*6*0001~GE*1*1~IEA*1*000000001~"] }

# Run the Actor and wait for it to finish
run = client.actor("nibble/edi-to-json").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "ediText": [
    "ISA*00*          *00*          *ZZ*ACMEBUYER      *ZZ*SUPPLYCO       *240115*1200*U*00401*000000001*0*P*>~GS*PO*ACMEBUYER*SUPPLYCO*20240115*1200*1*X*004010~ST*850*0001~BEG*00*NE*PO10001**20240115~N1*BY*ACME CORP*92*ACME01~PO1*1*10*EA*9.99*PE*BP*WIDGET-1~CTT*1~SE*6*0001~GE*1*1~IEA*1*000000001~"
  ]
}' |
apify call nibble/edi-to-json --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=nibble/edi-to-json",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "EDI to JSON Parser - X12 & EDIFACT (850/810/856/997)",
        "description": "Parse B2B EDI interchanges (X12 and EDIFACT) into clean structured JSON with optional structural validation. Purchase orders, invoices, ASNs and acknowledgments — no mapping setup.",
        "version": "0.0",
        "x-build-id": "F6ZeOwdDsIn4X2NOe"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/nibble~edi-to-json/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-nibble-edi-to-json",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/nibble~edi-to-json/runs": {
            "post": {
                "operationId": "runs-sync-nibble-edi-to-json",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/nibble~edi-to-json/run-sync": {
            "post": {
                "operationId": "run-sync-nibble-edi-to-json",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "ediText": {
                        "title": "Inline EDI text",
                        "type": "array",
                        "description": "Raw EDI interchange strings passed inline (X12 or EDIFACT) — convenient for API or AI-agent callers that send the data directly instead of by URL. Each string is parsed into one structured record.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "ediUrls": {
                        "title": "EDI URLs",
                        "type": "array",
                        "description": "Public URLs of EDI files to parse. Each is downloaded (with retries) and parsed to structured JSON.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "keyValueStoreKeys": {
                        "title": "Key-value store keys (uploaded files)",
                        "type": "array",
                        "description": "Keys in this run's default key-value store that hold EDI bytes. This is how files uploaded via the Console form are passed to the Actor.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "validate": {
                        "title": "Structural validation",
                        "type": "boolean",
                        "description": "Run segment/element structural validation (envelope balance, ST/SE and UNH/UNT segment counts, control-number matching) and return a per-interchange error list. Turn off to skip validation and only parse.",
                        "default": true
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
