# DZero Python
A robust and easy-to-use Python implementation of the NCPDP Telecommunications Standard Version D.0 Message **parser** and **serializer**.
Ported from the original Ruby implementation battle-tested at [Instacart](https://www.instacart.com/opensource).
## Installation
```bash
pip install dzero-python
```
## Features
- ✅ Complete field mapping for all **26** D.0 Segment types.
- Access field values by simple names instead of 2-character identifiers (ex: `claim_segment['fill_number']` instead of `claim_segment['D3']`)
- ✅ Parse D.0 Requests or Responses with ease.
- ex: `Request.parse(your_raw_string)`
- ✅ Build D.0 Requests or Responses programmatically.
- ex: `Request(...)` (see [Building](#building) below)
- ✅ Supports multiple transaction groups
- ex: `request.transaction_groups[2].claim_segment`
- ✅ Serialize a D.0 message to JSON
- ex: `request.to_json()`
## Usage
### Parsing and Manipulating
#### Parsing
```python
from dzero_python import Request
request = Request.parse(raw_message_string)
```
The above snippet will return a new instance of `Request`.
#### Reading the header
```python
print(request.header)
# => {
# 'bin_number': '999999',
# 'version': 'D0',
# 'transaction_code': 'B1',
# 'processor_control_number': '',
# 'transaction_count': '1',
# 'service_provider_id_qualifier': '01',
# 'service_provider_id': '1111111111',
# 'date_of_service': '20181106',
# 'software': ''
# }
```
#### Reading a single segment
```python
request.transmission_group.patient_segment
# => <PatientSegment instance>
request.transmission_group.insurance_segment
# => <InsuranceSegment instance>
request.transaction_groups[0].claim_segment
# => <ClaimSegment instance>
request.transaction_groups[2].claim_segment
# => <ClaimSegment instance>
```
#### Reading a field in a segment
Fields of a segment can be accessed via dictionary-style access, which takes either a symbol or a string.
```python
segment = request.transaction_groups[0].claim_segment
# => <ClaimSegment instance>
segment['segment_identification']
# => "07"
segment['AM']
# => "07"
segment['quantity_dispensed']
# => "2000"
segment['E7']
# => "2000"
```
#### Modifying a field in a segment
Fields of a segment can be modified via dictionary-style access. If a segment or field does not yet exist when it is accessed, it will be created and added to the message.
```python
segment = request.transaction_groups[0].claim_segment
segment['quantity_dispensed']
# => "2000"
segment['quantity_dispensed'] = "9990"
# => "9990"
segment['E7']
# => "9990"
segment['E7'] = "5555"
# => "5555"
segment['quantity_dispensed']
# => "5555"
```
#### Serializing to JSON
`Request`, `Response`, `TransmissionGroup`, `TransactionGroup`, and `Segment` all have **`to_json`** methods.
```python
request.to_json()
```
**`to_json`** takes two options:
- **`readable`** - if this is True, symbols will be used for the fields of a segment, instead of the field identifiers.
- **`key_group_by_segment_sym`** - if this is True, groups will be objects instead of arrays of objects. A group object will be keyed by the segment identifiers it contains.
### Building
For messages with a single transaction group, you can pass segments in with the **`segments`** argument. DZero will automatically filter the segments into the correct locations (either the **`transmission_group`** or the first **`transaction_group`**)
```python
from dzero_python import Request
from dzero_python.segments import PatientSegment
request = Request(
header={
'bin_number': '999999',
'version': 'D0',
'transaction_code': 'B1',
'processor_control_number': '',
'transaction_count': '1',
'service_provider_id_qualifier': '01',
'service_provider_id': '1111111111',
'date_of_service': '20181106',
'software': ''
},
segments=[
PatientSegment({
'patient_first_name': 'AUSTIN',
'patient_last_name': 'PIVARNIK',
'patient_phone_number': '5555555555'
})
]
)
```
For more control over the structure of the message, you can manually construct the `transmission_group` and the `transaction_groups`.
```python
from dzero_python import Response
from dzero_python.transmissions.groups import TransmissionGroup, TransactionGroup
from dzero_python.segments import ResponseMessageSegment, ResponseStatusSegment
response = Response(
header={
'version': 'D0',
'transaction_code': 'B1',
'transaction_count': '1',
'header_response_status': 'A',
'service_provider_id_qualifier': '01',
'service_provider_id': '1111111111',
'date_of_service': '20181106'
},
transmission_group=TransmissionGroup(
segments=[
ResponseMessageSegment({
'message': 'TEST MESSAGE'
})
]
),
transaction_groups=[
TransactionGroup(
segments=[
ResponseStatusSegment({
'response_status': 'C'
})
]
),
TransactionGroup(
segments=[
ResponseStatusSegment({
'response_status': 'R'
})
]
)
]
)
```
### Stringifying a message
To render an instance of `Request` or `Response` into a D.0 string, simply call `to_s()` on the instance.
```python
request.to_s()
# => "999999D0B1 1011111111111 20181106 \u001E\u001CAM01\u001CCAAUSTIN\u001CCBPIVARNIK\u001CCQ5555555555"
```
### Serializing a message to JSON
```python
request.to_json(readable=True, key_group_by_segment_sym=True)
# => {
# "header": {
# "bin_number": "999999",
# "version": "D0",
# "transaction_code": "B1",
# "processor_control_number": "",
# "transaction_count": "1",
# "service_provider_id_qualifier": "01",
# "service_provider_id": "9999999999",
# "date_of_service": "11282018",
# "software": ""
# },
# "transmission_group": {
# "patient": {
# "segment_identification": "01",
# "patient_first_name": "AUSTIN",
# "patient_last_name": "PIVARNIK",
# "patient_street_address": "50 BEALE ST",
# "patient_city": "SAN FRANCISCO",
# "patient_state_or_province": "CA",
# "patient_zip_postal_code": "94105",
# "patient_phone_number": "5555555555"
# }
# },
# "transaction_groups": [
# {
# "claim": {
# "segment_identification": "07",
# "prescription_reference_number_qualifier": "1",
# "prescription_reference_number": "9999999999",
# "product_service_id_qualifier": "03",
# "product_service_id": "99999999999",
# "quantity_dispensed": "2000",
# "fill_number": "0",
# "days_supply": "1",
# "compound_code": "1",
# "dispense_as_written_product_selection_code": "0",
# "date_prescription_written": "20181025",
# "number_of_refills_authorized": "99",
# "prescription_origin_code": "1",
# "unit_of_measure": "EA",
# "level_of_service": "0",
# "patient_assignment_indicator": "Y",
# "pharmacy_service_type": "1"
# },
# "pricing": {
# "segment_identification": "11",
# "ingredient_cost_submitted": "A",
# "dispensing_fee_submitted": "{",
# "patient_paid_amount_submitted": "{",
# "percentage_sales_tax_rate_submitted": "1750{",
# "usual_and_customary_charge": "A",
# "gross_amount_due": "A",
# "basis_of_cost_determination": "01"
# }
# }
# ]
# }
```
## Development
This project is a Python port of the Ruby DZero library. It maintains API compatibility where possible while following Python conventions.
## License
MIT License - see LICENSE file for details.
## Contributing
Bug reports and pull requests are welcome on GitHub.
Raw data
{
"_id": null,
"home_page": "https://github.com/tylerwinn/dzero-python",
"name": "dzero-python",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "ncpdp healthcare pharmacy telecommunications d0 parser serializer",
"author": "Python Port of DZero",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/de/46/58d29ae92312a35af43b85a478b6ae49d78e5906f1e524c9ddb13dc7e4f3/dzero_python-1.0.2.tar.gz",
"platform": null,
"description": "# DZero Python\r\n\r\nA robust and easy-to-use Python implementation of the NCPDP Telecommunications Standard Version D.0 Message **parser** and **serializer**.\r\n\r\nPorted from the original Ruby implementation battle-tested at [Instacart](https://www.instacart.com/opensource).\r\n\r\n## Installation\r\n\r\n```bash\r\npip install dzero-python\r\n```\r\n\r\n## Features\r\n\r\n- \u2705 Complete field mapping for all **26** D.0 Segment types.\r\n - Access field values by simple names instead of 2-character identifiers (ex: `claim_segment['fill_number']` instead of `claim_segment['D3']`)\r\n- \u2705 Parse D.0 Requests or Responses with ease.\r\n - ex: `Request.parse(your_raw_string)`\r\n- \u2705 Build D.0 Requests or Responses programmatically.\r\n - ex: `Request(...)` (see [Building](#building) below)\r\n- \u2705 Supports multiple transaction groups\r\n - ex: `request.transaction_groups[2].claim_segment`\r\n- \u2705 Serialize a D.0 message to JSON\r\n - ex: `request.to_json()`\r\n\r\n## Usage\r\n\r\n### Parsing and Manipulating\r\n\r\n#### Parsing\r\n\r\n```python\r\nfrom dzero_python import Request\r\n\r\nrequest = Request.parse(raw_message_string)\r\n```\r\n\r\nThe above snippet will return a new instance of `Request`.\r\n\r\n#### Reading the header\r\n\r\n```python\r\nprint(request.header)\r\n# => {\r\n# 'bin_number': '999999',\r\n# 'version': 'D0', \r\n# 'transaction_code': 'B1',\r\n# 'processor_control_number': '',\r\n# 'transaction_count': '1',\r\n# 'service_provider_id_qualifier': '01',\r\n# 'service_provider_id': '1111111111',\r\n# 'date_of_service': '20181106',\r\n# 'software': ''\r\n# }\r\n```\r\n\r\n#### Reading a single segment\r\n\r\n```python\r\nrequest.transmission_group.patient_segment\r\n# => <PatientSegment instance>\r\n\r\nrequest.transmission_group.insurance_segment \r\n# => <InsuranceSegment instance>\r\n\r\nrequest.transaction_groups[0].claim_segment\r\n# => <ClaimSegment instance>\r\n\r\nrequest.transaction_groups[2].claim_segment\r\n# => <ClaimSegment instance>\r\n```\r\n\r\n#### Reading a field in a segment\r\n\r\nFields of a segment can be accessed via dictionary-style access, which takes either a symbol or a string.\r\n\r\n```python\r\nsegment = request.transaction_groups[0].claim_segment\r\n# => <ClaimSegment instance>\r\n\r\nsegment['segment_identification']\r\n# => \"07\"\r\n\r\nsegment['AM'] \r\n# => \"07\"\r\n\r\nsegment['quantity_dispensed']\r\n# => \"2000\"\r\n\r\nsegment['E7']\r\n# => \"2000\"\r\n```\r\n\r\n#### Modifying a field in a segment\r\n\r\nFields of a segment can be modified via dictionary-style access. If a segment or field does not yet exist when it is accessed, it will be created and added to the message.\r\n\r\n```python\r\nsegment = request.transaction_groups[0].claim_segment\r\n\r\nsegment['quantity_dispensed']\r\n# => \"2000\"\r\n\r\nsegment['quantity_dispensed'] = \"9990\"\r\n# => \"9990\"\r\n\r\nsegment['E7']\r\n# => \"9990\"\r\n\r\nsegment['E7'] = \"5555\" \r\n# => \"5555\"\r\n\r\nsegment['quantity_dispensed']\r\n# => \"5555\"\r\n```\r\n\r\n#### Serializing to JSON\r\n\r\n`Request`, `Response`, `TransmissionGroup`, `TransactionGroup`, and `Segment` all have **`to_json`** methods.\r\n\r\n```python\r\nrequest.to_json()\r\n```\r\n\r\n**`to_json`** takes two options:\r\n- **`readable`** - if this is True, symbols will be used for the fields of a segment, instead of the field identifiers.\r\n- **`key_group_by_segment_sym`** - if this is True, groups will be objects instead of arrays of objects. A group object will be keyed by the segment identifiers it contains.\r\n\r\n### Building\r\n\r\nFor messages with a single transaction group, you can pass segments in with the **`segments`** argument. DZero will automatically filter the segments into the correct locations (either the **`transmission_group`** or the first **`transaction_group`**)\r\n\r\n```python\r\nfrom dzero_python import Request\r\nfrom dzero_python.segments import PatientSegment\r\n\r\nrequest = Request(\r\n header={\r\n 'bin_number': '999999',\r\n 'version': 'D0',\r\n 'transaction_code': 'B1', \r\n 'processor_control_number': '',\r\n 'transaction_count': '1',\r\n 'service_provider_id_qualifier': '01',\r\n 'service_provider_id': '1111111111',\r\n 'date_of_service': '20181106',\r\n 'software': ''\r\n },\r\n segments=[\r\n PatientSegment({\r\n 'patient_first_name': 'AUSTIN',\r\n 'patient_last_name': 'PIVARNIK', \r\n 'patient_phone_number': '5555555555'\r\n })\r\n ]\r\n)\r\n```\r\n\r\nFor more control over the structure of the message, you can manually construct the `transmission_group` and the `transaction_groups`.\r\n\r\n```python\r\nfrom dzero_python import Response\r\nfrom dzero_python.transmissions.groups import TransmissionGroup, TransactionGroup \r\nfrom dzero_python.segments import ResponseMessageSegment, ResponseStatusSegment\r\n\r\nresponse = Response(\r\n header={\r\n 'version': 'D0',\r\n 'transaction_code': 'B1',\r\n 'transaction_count': '1',\r\n 'header_response_status': 'A',\r\n 'service_provider_id_qualifier': '01', \r\n 'service_provider_id': '1111111111',\r\n 'date_of_service': '20181106'\r\n },\r\n transmission_group=TransmissionGroup(\r\n segments=[\r\n ResponseMessageSegment({\r\n 'message': 'TEST MESSAGE'\r\n })\r\n ]\r\n ),\r\n transaction_groups=[\r\n TransactionGroup(\r\n segments=[\r\n ResponseStatusSegment({\r\n 'response_status': 'C'\r\n })\r\n ]\r\n ),\r\n TransactionGroup(\r\n segments=[\r\n ResponseStatusSegment({\r\n 'response_status': 'R' \r\n })\r\n ]\r\n )\r\n ]\r\n)\r\n```\r\n\r\n### Stringifying a message\r\n\r\nTo render an instance of `Request` or `Response` into a D.0 string, simply call `to_s()` on the instance.\r\n\r\n```python\r\nrequest.to_s()\r\n# => \"999999D0B1 1011111111111 20181106 \\u001E\\u001CAM01\\u001CCAAUSTIN\\u001CCBPIVARNIK\\u001CCQ5555555555\"\r\n```\r\n\r\n### Serializing a message to JSON\r\n\r\n```python\r\nrequest.to_json(readable=True, key_group_by_segment_sym=True)\r\n# => {\r\n# \"header\": {\r\n# \"bin_number\": \"999999\",\r\n# \"version\": \"D0\", \r\n# \"transaction_code\": \"B1\",\r\n# \"processor_control_number\": \"\",\r\n# \"transaction_count\": \"1\",\r\n# \"service_provider_id_qualifier\": \"01\",\r\n# \"service_provider_id\": \"9999999999\",\r\n# \"date_of_service\": \"11282018\", \r\n# \"software\": \"\"\r\n# },\r\n# \"transmission_group\": {\r\n# \"patient\": {\r\n# \"segment_identification\": \"01\",\r\n# \"patient_first_name\": \"AUSTIN\",\r\n# \"patient_last_name\": \"PIVARNIK\",\r\n# \"patient_street_address\": \"50 BEALE ST\",\r\n# \"patient_city\": \"SAN FRANCISCO\", \r\n# \"patient_state_or_province\": \"CA\",\r\n# \"patient_zip_postal_code\": \"94105\",\r\n# \"patient_phone_number\": \"5555555555\"\r\n# }\r\n# },\r\n# \"transaction_groups\": [\r\n# {\r\n# \"claim\": {\r\n# \"segment_identification\": \"07\",\r\n# \"prescription_reference_number_qualifier\": \"1\",\r\n# \"prescription_reference_number\": \"9999999999\",\r\n# \"product_service_id_qualifier\": \"03\", \r\n# \"product_service_id\": \"99999999999\",\r\n# \"quantity_dispensed\": \"2000\",\r\n# \"fill_number\": \"0\",\r\n# \"days_supply\": \"1\", \r\n# \"compound_code\": \"1\",\r\n# \"dispense_as_written_product_selection_code\": \"0\",\r\n# \"date_prescription_written\": \"20181025\",\r\n# \"number_of_refills_authorized\": \"99\",\r\n# \"prescription_origin_code\": \"1\",\r\n# \"unit_of_measure\": \"EA\",\r\n# \"level_of_service\": \"0\",\r\n# \"patient_assignment_indicator\": \"Y\",\r\n# \"pharmacy_service_type\": \"1\"\r\n# },\r\n# \"pricing\": {\r\n# \"segment_identification\": \"11\",\r\n# \"ingredient_cost_submitted\": \"A\",\r\n# \"dispensing_fee_submitted\": \"{\",\r\n# \"patient_paid_amount_submitted\": \"{\", \r\n# \"percentage_sales_tax_rate_submitted\": \"1750{\",\r\n# \"usual_and_customary_charge\": \"A\",\r\n# \"gross_amount_due\": \"A\",\r\n# \"basis_of_cost_determination\": \"01\"\r\n# }\r\n# }\r\n# ]\r\n# }\r\n```\r\n\r\n## Development\r\n\r\nThis project is a Python port of the Ruby DZero library. It maintains API compatibility where possible while following Python conventions.\r\n\r\n## License\r\n\r\nMIT License - see LICENSE file for details.\r\n\r\n## Contributing\r\n\r\nBug reports and pull requests are welcome on GitHub.\r\n",
"bugtrack_url": null,
"license": null,
"summary": "NCPDP Telecommunications Standard Version D.0 Message parser and serializer",
"version": "1.0.2",
"project_urls": {
"Homepage": "https://github.com/tylerwinn/dzero-python"
},
"split_keywords": [
"ncpdp",
"healthcare",
"pharmacy",
"telecommunications",
"d0",
"parser",
"serializer"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "bd71b239455d99fc167f56dd71327b543d59094c25b011cf0dd70b40d4679eec",
"md5": "20fe660d07937527d538fbaf53fe2bad",
"sha256": "d804b0b1890a1b70dd28f483332f4278adc0b692e00cba9e841e2cfe5909824f"
},
"downloads": -1,
"filename": "dzero_python-1.0.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "20fe660d07937527d538fbaf53fe2bad",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 37381,
"upload_time": "2025-07-22T18:14:56",
"upload_time_iso_8601": "2025-07-22T18:14:56.572876Z",
"url": "https://files.pythonhosted.org/packages/bd/71/b239455d99fc167f56dd71327b543d59094c25b011cf0dd70b40d4679eec/dzero_python-1.0.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "de4658d29ae92312a35af43b85a478b6ae49d78e5906f1e524c9ddb13dc7e4f3",
"md5": "071b667d2b896361fbdf734cd793f490",
"sha256": "c2c005402a69c6b4543ad2df6b45e9e484dfbd8eded4396c27d3ce55fba7ccc7"
},
"downloads": -1,
"filename": "dzero_python-1.0.2.tar.gz",
"has_sig": false,
"md5_digest": "071b667d2b896361fbdf734cd793f490",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 22935,
"upload_time": "2025-07-22T18:14:57",
"upload_time_iso_8601": "2025-07-22T18:14:57.727615Z",
"url": "https://files.pythonhosted.org/packages/de/46/58d29ae92312a35af43b85a478b6ae49d78e5906f1e524c9ddb13dc7e4f3/dzero_python-1.0.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-22 18:14:57",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "tylerwinn",
"github_project": "dzero-python",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "dzero-python"
}