<?xml version="1.0" encoding="utf-8"?>
<!-- name="GENERATOR" content="github.com/mmarkdown/mmark Mmark Markdown Processor - mmark.miek.nl" -->
<rfc version="3" ipr="trust200902" docName="draft-wullink-rpp-json-00" submissionType="IETF" category="std" xml:lang="en" xmlns:xi="http://www.w3.org/2001/XInclude" indexInclude="true" tocDepth="4">

<front>
<title abbrev="XML to JSON for RPP">EPP XML to RPP JSON conversion rules</title><seriesInfo value="draft-wullink-rpp-json-00" stream="IETF" status="standard" name="Internet-Draft"></seriesInfo>
<author initials="M." surname="Wullink" fullname="Maarten Wullink"><organization>SIDN Labs</organization><address><postal><street></street>
</postal><email>maarten.wullink@sidn.nl</email>
<uri>https://sidn.nl/</uri>
</address></author><author initials="P." surname="Kowalik" fullname="Pawel Kowalik"><organization>DENIC</organization><address><postal><street></street>
</postal><email>pawel.kowalik@denic.de</email>
<uri>https://denic.de/</uri>
</address></author><date/>
<area>Internet</area>
<workgroup>Network Working Group</workgroup>

<abstract>
<t>This document describes the rules for converting The Extensible Provisioning Protocol (EPP) <xref target="RFC5730"></xref> XML based messages to a JSON <xref target="RFC8259"></xref> for use with the RESTful Provisioning Protocol (RPP).</t>
</abstract>

</front>

<middle>

<section anchor="introduction"><name>Introduction</name>
<t>EPP <xref target="RFC5730"></xref> employs XML to define its protocol interactions, with XML Schema Definitions (XSD) serving as the formal schema language to outline the structure and validate the conformance of EPP XML messages. These XSDs, integral to the EPP RFCs, ensure that EPP messages adhere to the expected syntax and semantic rules. This document describes the rules and methodologies for converting these XSDs, to JSON Schema, which serves a similar purpose for JSON formatted data. JSON Schema provides a robust framework for describing and validating the structure of JSON data, offering a parallel method for enforcing syntactical correctness and logical consistency in JSON formatted EPP messages.</t>
<t>As the domain registration industry evolves towards adopting RESTful APIs and other JSON-based interactions, there's a need for analogous schema definitions to ensure consistency, validation, and interoperability of JSON representations of EPP messages. This document aims to bridge this gap by providing a standardized approach to translating the rigorously defined XSDs of EPP into JSON Schema, facilitating the use of JSON in the RESTful Provisioning Protocol and potential future EPP-related protocols and transports.</t>
<t>This approach eventually allows for converting valid EPP XML messages to the JavaScript Object Notation (JSON) Data Interchange Format <xref target="RFC8259"></xref>, for use with EPP.</t>

<section anchor="motivation"><name>Motivation</name>
<t>The RESTful Provisioning Protocol (RPP) introduces a new provisiong mechanism that aligns more closely with modern cloud infrastructure, enhancing the scalability of server deployments. While RESTful protocols do not mandate a specific media type for resource description, the widespread adoption of JSON in web services has established it as the de facto standard for modern APIs. The increasing availability of tools, software libraries, and a skilled workforce, coupled with the declining popularity of XML, has led several registries to adopt JSON for data exchange within their API ecosystems. Registries supporting JSON, can offer a unified API ecosystem that extends beyond domain name and IP address provisioning, maintaining a consistent technology stack, data formats, and developer experience.</t>
<t>JSON's syntax, known for its straightforwardness and minimal verbosity compared to XML, significantly eases the tasks of writing, reading, and maintaining code. This simplicity is especially advantageous for the rapid comprehension and integration of provisioning APIs.</t>
<t>The lightweight nature of JSON can result in faster processing and data transfers, a critical aspect in high-volume transaction environments such as domain registration. Enhanced API response times can lead to more efficient domain lookups, registrations, and updates. Moreover, JSON parsing is typically faster and more straightforward than XML parsing, contributing to improved system performance amid frequent interactions between RPP clients and servers.</t>
<t>However, the absence of a standardized JSON format for domain provisioning has led to the emergence of TLD-specific implementations that lack interoperability, increasing the development effort required for integration. Similarly, at the registrar level, the absence of standards has resulted in numerous incompatible API implementations provided to clients and resellers. Standardizing a JSON format for domain provisioning within the RPP framework could mitigate these challenges, reducing fragmentation and simplifying integration efforts across the domain registration industry.</t>
</section>
</section>

<section anchor="terminology"><name>Terminology</name>
<t>In this document the following terminology is used.</t>
<t>EPP RFCs - This is a reference to the EPP version 1.0
specifications <xref target="RFC5730"></xref>, <xref target="RFC5731"></xref>, <xref target="RFC5732"></xref> and <xref target="RFC5733"></xref>.</t>
<t>RESTful Provisioning Protocol - A RESTful protocol for provisiong heterogeneous database objects.</t>
</section>

<section anchor="conventions-used-in-this-document"><name>Conventions Used in This Document</name>
<t>The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;,
&quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this
document are to be interpreted as described in <xref target="RFC2119"></xref>.</t>
<t>JSON is case sensitive. Unless stated otherwise, JSON specifications and examples provided in this document MUST be interpreted in the
character case presented. The examples in this document assume that request and response messages
are properly formatted JSON documents. Indentation and white space in examples are provided only to illustrate element relationships and for improving readability, and are not REQUIRED features of the protocol.</t>
</section>

<section anchor="xsd-conversion-rules"><name>XSD Conversion Rules</name>
<t>This chapter presents rules for converting EPP XSD into JSON Schema.</t>

<section anchor="elements-and-attributes"><name>Elements and Attributes</name>
<t>Rule 1: Elements in XSD must be converted to properties in the JSON Schema, preserving names.</t>
<t>XSD:</t>

<sourcecode type="xml"><![CDATA[<element name="name" type="eppcom:labelType"/>
]]>
</sourcecode>
<t>JSON Schema:</t>

<sourcecode type="json"><![CDATA[{
  ...
  "properties": {
    "name": {
      "$ref": "#/definitions/labelType"
    }
    ...
  }
}
]]>
</sourcecode>
<t>Rule 2: Attributes in XSD must be represented as JSON properties, prefixed with &quot;@&quot;, retaining original names with the prefix addition.</t>
<t>XSD:</t>

<sourcecode type="xml"><![CDATA[<simpleContent>
    <extension base="normalizedString">
    <attribute name="s" type="domain:statusValueType" use="required"/>
    <attribute name="lang" type="language"/>
    </extension>
</simpleContent>
]]>
</sourcecode>
<t>JSON Schema</t>

<sourcecode type="json"><![CDATA[{
  ...
  "properties": {
    "@s": {
      "$ref": "#/definitions/statusValueType"
    },
    "@lang": {
      "$ref": "#/definitions/language"
    }
    ...
  },
  "required": ["@s"]
}
]]>
</sourcecode>
</section>

<section anchor="simple-types-and-enumerations"><name>Simple Types and Enumerations</name>
<t>Rule 3: Simple types, including elements with only text content, must be converted to appropriate JSON types, e.g., xs:string to type: string.</t>
<t>XSD:</t>

<sourcecode type="xml"><![CDATA[<simpleType name="labelType">
  <restriction base="xs:string" />
</simpleType>
]]>
</sourcecode>
<t>JSON Schema:</t>

<artwork><![CDATA[{
  "definitions": {
    "labelType": {
      "type": "string"
    }
  }
}
]]>
</artwork>
<t>Rule 4: Enumerations in XSD must be represented using the enum keyword in JSON Schema.</t>
<t>XSD:</t>

<sourcecode type="xml"><![CDATA[<simpleType name="trStatusType">
  <restriction base="token">
    <enumeration value="clientApproved"/>
    <enumeration value="clientCancelled"/>
    ...
  </restriction>
</simpleType>
]]>
</sourcecode>
<t>JSON Schema:</t>

<sourcecode type="json"><![CDATA[{
  "definitions": {
    "trStatusType": {
      "type": "string",
      "enum": [
        "clientApproved",
        "clientCancelled",
        ...
      ]
    }
  }
}
]]>
</sourcecode>
</section>

<section anchor="occurrence-constraints"><name>Occurrence Constraints</name>
<t>Rule 5: Elements with minOccurs: 0 and maxOccurs: 1 should be represented as optional properties in the JSON Schema.</t>
<t>XSD:</t>

<sourcecode type="xml"><![CDATA[  <complexType name="infoType">
    <sequence>
      <element name="authInfo" type="authInfoType" minOccurs="0"/>
      ...
    </sequence>
  </complexType>
]]>
</sourcecode>
<t>JSON Schema:</t>

<sourcecode type="json"><![CDATA[{
  "type": "object",
  "properties": {
    "authInfo": {
      "$ref": "#/definitions/authInfoType"
    }
    ...
  },
  "required": []
}
]]>
</sourcecode>
<t>Rule 6: Elements with minOccurs: 1 and maxOccurs: 1 or omitted attributes must be represented as mandatory properties in the JSON Schema.</t>
<t>XSD:</t>

<sourcecode type="xml"><![CDATA[<xs:complexType name="createType">
  <xs:sequence>
    <xs:element name="name" type="xs:string"/>
    ...
  </xs:sequence>
</xs:complexType>
]]>
</sourcecode>
<t>JSON Schema:</t>

<sourcecode type="json"><![CDATA[{
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    }
    ...
  },
  "required": ["name"]
}
]]>
</sourcecode>
<t>Rule 7: Elements allowing multiple occurrences must be represented as JSON arrays, using minItems and maxItems to enforce minOccurs and maxOccurs.</t>
<t>XSD:</t>

<sourcecode type="xml"><![CDATA[  <complexType name="mNameType">
    <sequence>
      <element name="name" type="eppcom:labelType" maxOccurs="10"/>
    </sequence>
  </complexType>
]]>
</sourcecode>
<t>JSON Schema:</t>

<sourcecode type="json"><![CDATA[{
  "type": "object",
  "properties": {
    "name": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/labelType"
      },
      "maxItems" : 10
    }
  }
}
]]>
</sourcecode>
</section>

<section anchor="complex-types"><name>Complex Types</name>
<t>Rule 8: Complex types in XSD must be converted to JSON objects in the JSON Schema, with properties adhering to subsequent rules for elements and attributes. Properties rendered through choice or sequence elements included in complex types shall be included in the same object definition as opposed to creating a separate object level.</t>
<t>XSD:</t>

<sourcecode type="xml"><![CDATA[  <complexType name="createType">
    <sequence>
      <element name="name" type="eppcom:labelType"/>
      <element name="period" type="domain:periodType" minOccurs="0"/>
      ...
    </sequence>
  </complexType>
]]>
</sourcecode>
<t>JSON Schema:</t>

<sourcecode type="json"><![CDATA[{
    "title": "createType",
    "type": "object",
    "properties": {
        "name": {
            "$ref": "#/definitions/labelType"
        },
        "period": {
            "$ref": "#/definitions/periodType"
        },
        ...
    },
    "required": ["name", ...]
}
]]>
</sourcecode>
</section>

<section anchor="sequences"><name>Sequences</name>
<t>Rule 9: Sequences in XSD must be converted to JSON objects in the JSON Schema, with each sequence element becoming a property of the object. Cardinality dictated by minOccurs and maxOccurs must be applied to determine if an element is represented as optional, mandatory, or an array.</t>
<t>XSD:</t>

<sourcecode type="xml"><![CDATA[  <complexType name="createType">
    <sequence>
      <element name="name" type="eppcom:labelType"/>
      <element name="period" type="domain:periodType" minOccurs="0"/>
      ...
    </sequence>
  </complexType>
]]>
</sourcecode>
<t>JSON Schema:</t>

<sourcecode type="json"><![CDATA[{
    "title": "createType",
    "type": "object",
    "properties": {
        "name": {
            "$ref": "#/definitions/labelType"
        },
        "period": {
            "$ref": "#/definitions/periodType"
        },
        ...
    },
    "required": ["name", ...]
}
]]>
</sourcecode>
</section>

<section anchor="choices"><name>Choices</name>
<t>Rule 10: The choice construct in XSD must be represented in JSON Schema using the oneOf keyword, allowing for representation of multiple possible structures with only one being valid at a time. Each choice property MUST be marked as required to make a clear and unambigous distinction between the variants.</t>
<t>XSD:</t>

<sourcecode type="xml"><![CDATA[<complexType name="authInfoChgType">
  <choice>
    <element name="pw" type="eppcom:pwAuthInfoType"/>
    <element name="ext" type="eppcom:extAuthInfoType"/>
    ...
  </choice>
</complexType>

]]>
</sourcecode>
<t>JSON Schema:</t>

<sourcecode type="json"><![CDATA[{
  "type": "object",
  "oneOf": [
    {
      "properties": {
        "pw": {
          "$ref": "#/definitions/pwAuthInfoType"
        }
      },
      "required": ["pw"]
    },
    {
      "properties": {
        "ext": {
          "$ref": "#/definitions/extAuthInfoType"
        }
      },
      "required": ["ext"]
    }
    ...
  ]
}
]]>
</sourcecode>
</section>

<section anchor="mixed-content-and-special-cases"><name>Mixed Content and Special Cases</name>
<t>Rule 11: Elements with mixed content must be represented as JSON objects with #text for text content and properties for each child element. If schema allows for multiple instances of text content the #text property should be defined as an array.</t>
<t>XSD:</t>

<sourcecode type="xml"><![CDATA[  <complexType name="errValueType" mixed="true">
    <sequence>
      <any namespace="##any" processContents="skip"/>
    </sequence>
    <anyAttribute namespace="##any" processContents="skip"/>
  </complexType>
]]>
</sourcecode>
<t>JSON Schema:</t>

<sourcecode type="json"><![CDATA[{
  "type": "object",
  "properties": {
    "#text": {
      "type": "array",
      "items": {
        "type": string
      }
    },
    "additionalProperties": true
  }
}
]]>
</sourcecode>
<t>Rule 12: Empty elements in XSD or EPP normative text must be represented as properties with a null fixed value in the JSON Schema.</t>
<t>XSD:</t>

<sourcecode type="xml"><![CDATA[<complexType name="eppType">
    <choice>
      ...
      <element name="hello"/>
      ...
    </choice>
</complexType>
]]>
</sourcecode>
<t>JSON Schema:</t>

<sourcecode type="json"><![CDATA[{
  "type": "object",
  "oneOf": [
    ...
    {
        "properties": {
            "hello": {
                "type": "null"
            }
        },
        "required": ["hello"]
    }
    ...
  ]
}
]]>
</sourcecode>
<t>Rule 13: Elements with attributes and text content must be represented as JSON objects with #text for text and properties for each attribute, prefixed with &quot;@&quot;.</t>
<t>XSD:</t>

<sourcecode type="xml"><![CDATA[  <complexType name="mixedMsgType" mixed="true">
    <sequence>
      <any processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
    </sequence>
    <attribute name="lang" type="language" default="en"/>
  </complexType>
]]>
</sourcecode>
<t>JSON Schema:</t>

<sourcecode type="json"><![CDATA[{
  "type": "object",
  "properties": {
    "#text": {
      "type": "array",
      "items": {
        "type": string
      }
    },
    "@lang": {
        "$ref": "#/definitions/language"
    },
    "additionalProperties": true
  }
}
]]>
</sourcecode>

<artwork><![CDATA[TODO: Rules for different flavours of token type (min/max characters etc.)
]]>
</artwork>

<artwork><![CDATA[TODO: merge the content examples with the rules above?
]]>
</artwork>
</section>
</section>

<section anchor="xml-conversion-rules"><name>XML Conversion Rules</name>
<t>A XML element may exist in one of 7 distinct forms, the sections below describe how these forms MUST be translated to valid JSON.</t>

<ol spacing="compact">
<li>Empty</li>
<li>Pure text content</li>
<li>Attributes only</li>
<li>Pure text content and attributes</li>
<li>Child elements with different names</li>
<li>Child elements with identical names</li>
<li>Child element(s) and contiguous text</li>
</ol>

<section anchor="empty"><name>Empty</name>
<t>An empty XML element MUST be mapped to to a key matching the name of the element and a null value.</t>
<t>XML:</t>

<sourcecode type="xml"><![CDATA[<hello/>
]]>
</sourcecode>
<t>JSON:</t>

<sourcecode type="json"><![CDATA[{
    "hello": null
}
]]>
</sourcecode>
</section>

<section anchor="pure-text-content"><name>Pure text content</name>
<t>An XML element containing text only MUST be mapped to a key matching the name of the element and the text MUST be used for the value</t>
<t>XML:</t>

<sourcecode type="xml"><![CDATA[<lang>en</lang>
]]>
</sourcecode>
<t>JSON:</t>

<sourcecode type="json"><![CDATA[{
    "lang": "en"
}
]]>
</sourcecode>
</section>

<section anchor="attributes-only"><name>Attributes only</name>
<t>An XML element containing one or more atributes only, MUST be mapped to a JSON object matching the name of the element. Each XML attribute, prefixed using the <tt>@</tt> character, MUST be added as a key-value pair to the object.</t>
<t>XML:</t>

<sourcecode type="xml"><![CDATA[<msgQ count="5" id="12345"/>
]]>
</sourcecode>
<t>JSON:</t>

<sourcecode type="json"><![CDATA[{
    "msgQ": {
        "@count": "5",
        "@id": "12345"
    }
}
]]>
</sourcecode>
</section>

<section anchor="pure-text-content-and-attributes"><name>Pure text content and attributes</name>
<t>An XML element containing one or more atributes and text content only, MUST be mapped to a JSON object matching the name of the element. The text content MUST, prefixed using the string <tt>#text</tt>, MUST be added as a key-value pair to the object.</t>
<t>XML:</t>

<sourcecode type="xml"><![CDATA[<msg lang="en">Command completed successfully</msg>
]]>
</sourcecode>
<t>JSON:</t>

<sourcecode type="json"><![CDATA[{
    "msg": {
        "@lang": "en",
        "#text": "Command completed successfully"
    }
}
]]>
</sourcecode>
</section>

<section anchor="child-elements-with-different-names"><name>Child elements with different names</name>
<t>An XML element containing one or more child elements, where each child uses an unique name, MUST be mapped to a JSON object matching the name of the element. Each child element MUST be added as a key-value pair to the parent object.</t>
<t>XML:</t>

<sourcecode type="xml"><![CDATA[<trID>
    <clTRID>ABC-12345</clTRID>
    <svTRID>54321-XYZ</svTRID>
</trID>
]]>
</sourcecode>
<t>JSON:</t>

<sourcecode type="json"><![CDATA[{
    "trID": {
        "clTRID": "ABC-12345",
        "svTRID": "54321-XYZ"
    }
}
]]>
</sourcecode>
</section>

<section anchor="child-elements-with-identical-names"><name>Child elements with identical names</name>
<t>An XML element containing multiple child elements, where multiple child elements use the same name, MUST be mapped to a JSON object containing an array. The name of the array MUST match the name of the non-unique children, each child element MUST be converted to JSON and added to the array.</t>
<t>XML:</t>

<sourcecode type="xml"><![CDATA[<host>
    <addr>192.0.2.1</addr>
    <addr>192.0.2.2</addr>
</host>
]]>
</sourcecode>
<t>JSON:</t>

<sourcecode type="json"><![CDATA[{
    "host": {
        "addr": [
            "192.0.2.1",
            "192.0.2.2"
        ]
    }
}
]]>
</sourcecode>
</section>

<section anchor="child-elements-and-contiguous-text"><name>Child elements and contiguous text</name>
<t>An XML element containing one or more child elements and contiguous text, MUST be mapped to a JSON object containing a key-value entry for each child element, the text value MUST result in a key named <tt>#text</tt>.</t>
<t>XML:</t>

<sourcecode type="xml"><![CDATA[<msg lang="en">
    Credit balance low.
    <limit>100</limit>
    <bal>5</bal>
</msg>
]]>
</sourcecode>
<t>JSON:</t>

<sourcecode type="json"><![CDATA[{
    "msg": {
        "@lang": "en",
        "limit": 100,
        "bal": 5,
        "#text": "Credit balance low."
    }
}
]]>
</sourcecode>
<t>When child elements are mixed with multiple text segments, the resulting <tt>#text</tt> key-value entry MUST be an array, containing all text segments.</t>
<t>XML:</t>

<sourcecode type="xml"><![CDATA[<msg lang="en">
    Credit balance low.
    <limit>100</limit>
    <bal>5</bal>
    Please increase balance.
</msg>
]]>
</sourcecode>
<t>JSON:</t>

<sourcecode type="json"><![CDATA[{
    "msg": {
        "@lang": "en",
        "limit": 100,
        "bal": 5,
        "#text": ["Credit balance low.", "Please increase balance asap."]
    }
}
]]>
</sourcecode>
<t>The rules above are based on the conversion approach found on <xref target="XMLCOM-WEB"></xref></t>
</section>
</section>

<section anchor="examples"><name>Examples</name>
<t>This section lists examples for each of the existing EPP commands that are support by RPP.</t>

<artwork><![CDATA[TODO: full examples of schema conversion
]]>
</artwork>

<section anchor="hello"><name>Hello</name>
<t>The Hello request message does not exist in the context of RPP.</t>
<t>Example XML response:</t>

<sourcecode type="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp
    xmlns="urn:ietf:params:xml:ns:epp-1.0">
    <greeting>
        <svID>Example EPP server epp.example.com</svID>
        <svDate>2000-06-08T22:00:00.0Z</svDate>
        <svcMenu>
            <version>1.0</version>
            <lang>en</lang>
            <lang>fr</lang>
            <objURI>urn:ietf:params:xml:ns:obj1</objURI>
            <objURI>urn:ietf:params:xml:ns:obj2</objURI>
            <objURI>urn:ietf:params:xml:ns:obj3</objURI>
            <svcExtension>
                <extURI>http://custom/obj1ext-1.0</extURI>
            </svcExtension>
        </svcMenu>
        <dcp>
            <access>
                <all/>
            </access>
            <statement>
                <purpose>
                    <admin/>
                    <prov/>
                </purpose>
                <recipient>
                    <ours/>
                    <public/>
                </recipient>
                <retention>
                    <stated/>
                </retention>
            </statement>
        </dcp>
    </greeting>
</epp>
]]>
</sourcecode>
<t>Example JSON response:</t>

<sourcecode type="json"><![CDATA[{
    "rpp": {
        "@xmlns": "urn:ietf:params:xml:ns:epp-1.0",
        "greeting": {
            "svID": "Example RPP server v1.0",
            "svDate": "2000-06-08T22:00:00.0Z",
            "svcMenu": {
                "version": "1.0",
                "lang": [
                    "en",
                    "fr"
                ]
            },
            "dcp": {
                "access": {
                    "all": null
                },
                "statement": {
                    "purpose": {
                        "admin": null,
                        "prov": null
                    },
                    "recipient": {
                        "ours": null,
                        "public": null
                    },
                    "retention": {
                        "stated": null
                    }
                }
            }
        }
    }
}
]]>
</sourcecode>
</section>

<section anchor="login"><name>Login</name>
<t>The Login request and response message are not used for RPP.</t>
</section>

<section anchor="logout"><name>Logout</name>
<t>The Logout request and response message are not used for RPP.</t>
</section>

<section anchor="check"><name>Check</name>
<t>The Check request and responses messages are not used for RPP.</t>
</section>

<section anchor="info"><name>Info</name>
<t>The Info request message is not used for RPP.</t>
<t>Example XML Domain Info response:</t>

<sourcecode type="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp
    xmlns="urn:ietf:params:xml:ns:epp-1.0">
    <response>
        <result code="1000">
            <msg>Command completed successfully</msg>
        </result>
        <resData>
            <domain:infData
                xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
                <domain:name>example.com</domain:name>
                <domain:roid>EXAMPLE1-REP</domain:roid>
                <domain:status s="ok"/>
                <domain:registrant>jd1234</domain:registrant>
                <domain:contact type="admin">sh8013</domain:contact>
                <domain:contact type="tech">sh8013</domain:contact>
                <domain:ns>
                    <domain:hostObj>ns1.example.com</domain:hostObj>
                    <domain:hostObj>ns1.example.net</domain:hostObj>
                </domain:ns>
                <domain:host>ns1.example.com</domain:host>
                <domain:host>ns2.example.com</domain:host>
                <domain:clID>ClientX</domain:clID>
                <domain:crID>ClientY</domain:crID>
                <domain:crDate>1999-04-03T22:00:00.0Z</domain:crDate>
                <domain:upID>ClientX</domain:upID>
                <domain:upDate>1999-12-03T09:00:00.0Z</domain:upDate>
                <domain:exDate>2005-04-03T22:00:00.0Z</domain:exDate>
                <domain:trDate>2000-04-08T09:00:00.0Z</domain:trDate>
                <domain:authInfo>
                    <domain:pw>2fooBAR</domain:pw>
                </domain:authInfo>
            </domain:infData>
        </resData>
        <trID>
            <clTRID>ABC-12345</clTRID>
            <svTRID>54322-XYZ</svTRID>
        </trID>
    </response>
</epp>
]]>
</sourcecode>
<t>Example JSON Domain Info response:</t>

<sourcecode type="json"><![CDATA[{
    "rpp": {
        "@xmlns": "urn:ietf:params:xml:ns:epp-1.0",
        "response": {
            "result": {
                "@code": "1000",
                "msg": "Command completed successfully"
            },
            "resData": {
                "domain:infData": {
                    "@xmlns:domain": "urn:ietf:params:xml:ns:domain-1.0",
                    "domain:name": "example.com",
                    "domain:roid": "EXAMPLE1-REP",
                    "domain:status": {
                        "@s": "ok"
                    },
                    "domain:registrant": "jd1234",
                    "domain:contact": [
                        {
                            "@type": "admin",
                            "#text": "sh8013"
                        },
                        {
                            "@type": "tech",
                            "#text": "sh8013"
                        }
                    ],
                    "domain:ns": {
                        "domain:hostObj": [
                            "ns1.example.com",
                            "ns1.example.net"
                        ]
                    },
                    "domain:host": [
                        "ns1.example.com",
                        "ns2.example.com"
                    ],
                    "domain:clID": "ClientX",
                    "domain:crID": "ClientY",
                    "domain:crDate": "1999-04-03T22:00:00.0Z",
                    "domain:upID": "ClientX",
                    "domain:upDate": "1999-12-03T09:00:00.0Z",
                    "domain:exDate": "2005-04-03T22:00:00.0Z",
                    "domain:trDate": "2000-04-08T09:00:00.0Z",
                    "domain:authInfo": {
                        "domain:pw": "2fooBAR"
                    }
                }
            },
            "trID": {
                "clTRID": "ABC-12345",
                "svTRID": "54322-XYZ"
            }
        }
    }
}
]]>
</sourcecode>
</section>

<section anchor="poll"><name>Poll</name>
<t>The Poll request message is not used for RPP.</t>
<t>Example XML response:</t>

<sourcecode type="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp
    xmlns="urn:ietf:params:xml:ns:epp-1.0">
    <response>
        <result code="1301">
            <msg>Command completed successfully; ack to dequeue</msg>
        </result>
        <msgQ count="4" id="12346">
            <qDate>2000-06-08T22:10:00.0Z</qDate>
            <msg lang="en">Credit balance low.
                <limit>100</limit>
                <bal>5</bal>
            </msg>
        </msgQ>
        <trID>
            <clTRID>ABC-12346</clTRID>
            <svTRID>54321-XYZ</svTRID>
        </trID>
    </response>
</epp>
]]>
</sourcecode>
<t>Example JSON response:</t>

<sourcecode type="json"><![CDATA[{
    "rpp": {
        "@xmlns": "urn:ietf:params:xml:ns:epp-1.0",
        "response": {
            "result": {
                "@code": "1301",
                "msg": "Command completed successfully; ack to dequeue"
            },
            "msgQ": {
                "@count": "4",
                "@id": "12346",
                "qDate": "2024-01-15T22:10:00.0Z",
                "msg": {
                    "@lang": "en",
                    "limit": "100",
                    "bal": "5",
                    "#text": "Credit balance low."
                }
            },
            "trID": {
                "clTRID": "ABC-12346",
                "svTRID": "54321-XYZ"
            }
        }
    }
}
]]>
</sourcecode>
</section>

<section anchor="poll-ack"><name>Poll Ack</name>
<t>The Poll Ack request message is not used for RPP.</t>
<t>Example XML response:</t>

<sourcecode type="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp
    xmlns="urn:ietf:params:xml:ns:epp-1.0">
    <response>
        <result code="1000">
            <msg>Command completed successfully</msg>
        </result>
        <msgQ count="0" id="12345"/>
        <trID>
            <clTRID>ABC-12345</clTRID>
            <svTRID>XYZ-12345</svTRID>
        </trID>
    </response>
</epp>
]]>
</sourcecode>
<t>Example JSON response:</t>

<sourcecode type="json"><![CDATA[{
    "rpp": {
        "@xmlns": "urn:ietf:params:xml:ns:epp-1.0",
        "response": {
            "result": {
                "@code": "1000",
                "msg": "Command completed successfully"
            },
            "msgQ": {
                "@count": "0",
                "@id": "12345"
            },
            "trID": {
                "clTRID": "ABC-12345",
                "svTRID": "XYZ-12345"
            }
        }
    }
}
]]>
</sourcecode>
</section>

<section anchor="transfer-query"><name>Transfer Query</name>
<t>The Domain Transfer Query request message is not used for RPP.</t>
<t>Example XML  Domain Transfer Query response:</t>

<sourcecode type="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp
    xmlns="urn:ietf:params:xml:ns:epp-1.0">
    <response>
        <result code="1000">
            <msg>Command completed successfully</msg>
        </result>
        <resData>
            <domain:trnData
                xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
                <domain:name>example.com</domain:name>
                <domain:trStatus>pending</domain:trStatus>
                <domain:reID>ClientX</domain:reID>
                <domain:reDate>2000-06-06T22:00:00.0Z</domain:reDate>
                <domain:acID>ClientY</domain:acID>
                <domain:acDate>2000-06-11T22:00:00.0Z</domain:acDate>
                <domain:exDate>2002-09-08T22:00:00.0Z</domain:exDate>
            </domain:trnData>
        </resData>
        <trID>
            <clTRID>ABC-12345</clTRID>
            <svTRID>54322-XYZ</svTRID>
        </trID>
    </response>
</epp>
]]>
</sourcecode>
<t>Example JSON Domain Transfer Query response:</t>

<sourcecode type="json"><![CDATA[{
    "rpp": {
        "@xmlns": "urn:ietf:params:xml:ns:epp-1.0",
        "response": {
            "result": {
                "@code": "1000",
                "msg": "Command completed successfully"
            },
            "resData": {
                "domain:trnData": {
                    "@xmlns:domain": "urn:ietf:params:xml:ns:domain-1.0",
                    "domain:name": "example.com",
                    "domain:trStatus": "pending",
                    "domain:reID": "ClientX",
                    "domain:reDate": "2000-06-06T22:00:00.0Z",
                    "domain:acID": "ClientY",
                    "domain:acDate": "2000-06-11T22:00:00.0Z",
                    "domain:exDate": "2002-09-08T22:00:00.0Z"
                }
            },
            "trID": {
                "clTRID": "ABC-12345",
                "svTRID": "54322-XYZ"
            }
        }
    }
}
]]>
</sourcecode>
</section>

<section anchor="create"><name>Create</name>
<t>Example XML Domain Create request:</t>

<sourcecode type="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp
    xmlns="urn:ietf:params:xml:ns:epp-1.0">
    <command>
        <create>
            <domain:create
                xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
                <domain:name>example.com</domain:name>
                <domain:period unit="y">2</domain:period>
                <domain:ns>
                    <domain:hostObj>ns1.example.net</domain:hostObj>
                    <domain:hostObj>ns2.example.net</domain:hostObj>
                </domain:ns>
                <domain:registrant>jd1234</domain:registrant>
                <domain:contact type="admin">sh8013</domain:contact>
                <domain:contact type="tech">sh8013</domain:contact>
                <domain:authInfo>
                    <domain:pw>2fooBAR</domain:pw>
                </domain:authInfo>
            </domain:create>
        </create>
        <clTRID>ABC-12345</clTRID>
    </command>
</epp>
]]>
</sourcecode>
<t>Example JSON Domain Create request:</t>

<sourcecode type="json"><![CDATA[{
    "rpp": {
        "@xmlns": "urn:ietf:params:xml:ns:epp-1.0",
        "command": {
            "create": {
                "domain:create": {
                    "@xmlns:domain": "urn:ietf:params:xml:ns:domain-1.0",
                    "domain:name": "example.com",
                    "domain:period": {
                        "@unit": "y",
                        "#text": "2"
                    },
                    "domain:ns": {
                        "domain:hostObj": [
                            "ns1.example.net",
                            "ns2.example.net"
                        ]
                    },
                    "domain:registrant": "jd1234",
                    "domain:contact": [
                        {
                            "@type": "admin",
                            "#text": "sh8013"
                        },
                        {
                            "@type": "tech",
                            "#text": "sh8013"
                        }
                    ],
                    "domain:authInfo": {
                        "domain:pw": "2fooBAR"
                    }
                }
            },
            "clTRID": "ABC-12345"
        }
    }
}
]]>
</sourcecode>
<t>Example XML Domain Create response:</t>

<sourcecode type="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp
    xmlns="urn:ietf:params:xml:ns:epp-1.0">
    <response>
        <result code="1000">
            <msg>Command completed successfully</msg>
        </result>
        <resData>
            <domain:creData
                xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
                <domain:name>example.com</domain:name>
                <domain:crDate>1999-04-03T22:00:00.0Z</domain:crDate>
                <domain:exDate>2001-04-03T22:00:00.0Z</domain:exDate>
            </domain:creData>
        </resData>
        <trID>
            <clTRID>ABC-12345</clTRID>
            <svTRID>54321-XYZ</svTRID>
        </trID>
    </response>
</epp>
]]>
</sourcecode>
<t>Example JSON Domain Create response:</t>

<sourcecode type="json"><![CDATA[{
    "rpp": {
        "@xmlns": "urn:ietf:params:xml:ns:epp-1.0",
        "response": {
            "result": {
                "@code": "1000",
                "msg": "Command completed successfully"
            },
            "resData": {
                "domain:creData": {
                    "@xmlns:domain": "urn:ietf:params:xml:ns:domain-1.0",
                    "domain:name": "example.com",
                    "domain:crDate": "1999-04-03T22:00:00.0Z",
                    "domain:exDate": "2001-04-03T22:00:00.0Z"
                }
            },
            "trID": {
                "clTRID": "ABC-12345",
                "svTRID": "54321-XYZ"
            }
        }
    }
}
]]>
</sourcecode>
</section>

<section anchor="delete"><name>Delete</name>
<t>The Delete request message is not used for RPP.</t>
<t>Example XML Domain Delete response:</t>

<sourcecode type="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp
    xmlns="urn:ietf:params:xml:ns:epp-1.0">
    <response>
        <result code="1000">
            <msg>Command completed successfully</msg>
        </result>
        <trID>
            <clTRID>ABC-12345</clTRID>
            <svTRID>54321-XYZ</svTRID>
        </trID>
    </response>
</epp>
]]>
</sourcecode>
<t>Example JSON Domain Delete response:</t>

<sourcecode type="json"><![CDATA[{
    "rpp": {
        "@xmlns": "urn:ietf:params:xml:ns:epp-1.0",
        "response": {
            "result": {
                "@code": "1000",
                "msg": "Command completed successfully"
            },
            "trID": {
                "clTRID": "ABC-12345",
                "svTRID": "54321-XYZ"
            }
        }
    }
}
]]>
</sourcecode>
</section>

<section anchor="renew"><name>Renew</name>
<t>The Renew request message is not used for RPP.</t>
<t>Example XML Domain Renew response:</t>

<sourcecode type="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp
    xmlns="urn:ietf:params:xml:ns:epp-1.0">
    <response>
        <result code="1000">
            <msg>Command completed successfully</msg>
        </result>
        <resData>
            <domain:renData
                xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
                <domain:name>example.com</domain:name>
                <domain:exDate>2005-04-03T22:00:00.0Z</domain:exDate>
            </domain:renData>
        </resData>
        <trID>
            <clTRID>ABC-12345</clTRID>
            <svTRID>54322-XYZ</svTRID>
        </trID>
    </response>
</epp>
]]>
</sourcecode>
<t>Example JSON Domain Renew response:</t>

<sourcecode type="json"><![CDATA[{
    "rpp": {
        "@xmlns": "urn:ietf:params:xml:ns:epp-1.0",
        "response": {
            "result": {
                "@code": "1000",
                "msg": "Command completed successfully"
            },
            "resData": {
                "domain:renData": {
                    "@xmlns:domain": "urn:ietf:params:xml:ns:domain-1.0",
                    "domain:name": "example.com",
                    "domain:exDate": "2005-04-03T22:00:00.0Z"
                }
            },
            "trID": {
                "clTRID": "ABC-12345",
                "svTRID": "54322-XYZ"
            }
        }
    }
}
]]>
</sourcecode>
</section>

<section anchor="transfer-request"><name>Transfer Request</name>
<t>The Transfer request message is not used for RPP.</t>
<t>Example XML Domain Transfer response:</t>

<sourcecode type="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp
    xmlns="urn:ietf:params:xml:ns:epp-1.0">
    <response>
        <result code="1001">
            <msg>Command completed successfully; action pending</msg>
        </result>
        <resData>
            <domain:trnData
                xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
                <domain:name>example.com</domain:name>
                <domain:trStatus>pending</domain:trStatus>
                <domain:reID>ClientX</domain:reID>
                <domain:reDate>2000-06-08T22:00:00.0Z</domain:reDate>
                <domain:acID>ClientY</domain:acID>
                <domain:acDate>2000-06-13T22:00:00.0Z</domain:acDate>
                <domain:exDate>2002-09-08T22:00:00.0Z</domain:exDate>
            </domain:trnData>
        </resData>
        <trID>
            <clTRID>ABC-12345</clTRID>
            <svTRID>54322-XYZ</svTRID>
        </trID>
    </response>
</epp>
]]>
</sourcecode>
<t>Example JSON Domain Transfer response:</t>

<sourcecode type="json"><![CDATA[{
    "rpp": {
        "@xmlns": "urn:ietf:params:xml:ns:epp-1.0",
        "response": {
            "result": {
                "@code": "1001",
                "msg": "Command completed successfully; action pending"
            },
            "resData": {
                "domain:trnData": {
                    "@xmlns:domain": "urn:ietf:params:xml:ns:domain-1.0",
                    "domain:name": "example.com",
                    "domain:trStatus": "pending",
                    "domain:reID": "ClientX",
                    "domain:reDate": "2000-06-08T22:00:00.0Z",
                    "domain:acID": "ClientY",
                    "domain:acDate": "2000-06-13T22:00:00.0Z",
                    "domain:exDate": "2002-09-08T22:00:00.0Z"
                }
            },
            "trID": {
                "clTRID": "ABC-12345",
                "svTRID": "54322-XYZ"
            }
        }
    }
}
]]>
</sourcecode>
</section>

<section anchor="transfer-cancel"><name>Transfer Cancel</name>
<t>The Transfer Cancel request message is not used for RPP.</t>
<t>Example XML Domain Cancel Transfer response:</t>

<sourcecode type="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp
    xmlns="urn:ietf:params:xml:ns:epp-1.0">
    <response>
        <result code="1000">
            <msg>Command completed successfully</msg>
        </result>
        <trID>
            <clTRID>ABC-12345</clTRID>
            <svTRID>XYZ-12345</svTRID>
        </trID>
    </response>
</epp>
]]>
</sourcecode>
<t>Example JSON Domain Cancel Transfer response:</t>

<sourcecode type="json"><![CDATA[{
    "rpp": {
        "@xmlns": "urn:ietf:params:xml:ns:epp-1.0",
        "response": {
            "result": {
                "@code": "1000",
                "msg": "Command completed successfully"
            },
            "trID": {
                "clTRID": "ABC-12345",
                "svTRID": "XYZ-12345"
            }
        }
    }
}
]]>
</sourcecode>
</section>

<section anchor="transfer-reject"><name>Transfer Reject</name>
<t>The Transfer Reject request message is not used for RPP and the response message is the same as for the Transfer Cancel command.</t>
</section>

<section anchor="transfer-approve"><name>Transfer Approve</name>
<t>The Transfer Approve request message is not used for RPP and the response message is the same as for the Transfer Cancel command.</t>
</section>

<section anchor="update"><name>Update</name>
<t>Example XML Domain Update request:</t>

<sourcecode type="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp
    xmlns="urn:ietf:params:xml:ns:epp-1.0">
    <command>
        <update>
            <domain:update
                xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
                <domain:name>example.com</domain:name>
                <domain:chg>
                    <domain:registrant>sh8013</domain:registrant>
                    <domain:authInfo>
                        <domain:pw>2BARfoo</domain:pw>
                    </domain:authInfo>
                </domain:chg>
            </domain:update>
        </update>
        <clTRID>ABC-12345</clTRID>
    </command>
</epp>
]]>
</sourcecode>
<t>Example JSON Domain Update request:</t>

<sourcecode type="json"><![CDATA[{
    "rpp": {
        "@xmlns": "urn:ietf:params:xml:ns:epp-1.0",
        "command": {
            "update": {
                "domain:update": {
                    "@xmlns:domain": "urn:ietf:params:xml:ns:domain-1.0",
                    "domain:name": "example.com",
                    "domain:chg": {
                        "domain:registrant": "sh8013",
                        "domain:authInfo": {
                            "domain:pw": "2BARfoo"
                        }
                    }
                }
            },
            "clTRID": "ABC-12345"
        }
    }
}
]]>
</sourcecode>
<t>Example XML Domain Update response:</t>

<sourcecode type="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp
    xmlns="urn:ietf:params:xml:ns:epp-1.0">
    <response>
        <result code="1000">
            <msg>Command completed successfully</msg>
        </result>
        <trID>
            <clTRID>ABC-12345</clTRID>
            <svTRID>XYZ-12345</svTRID>
        </trID>
    </response>
</epp>
]]>
</sourcecode>
<t>Example JSON Domain Update response:</t>

<sourcecode type="json"><![CDATA[{
    "rpp": {
        "@xmlns": "urn:ietf:params:xml:ns:epp-1.0",
        "response": {
            "result": {
                "@code": "1000",
                "msg": "Command completed successfully"
            },
            "trID": {
                "clTRID": "ABC-12345",
                "svTRID": "XYZ-12345"
            }
        }
    }
}
]]>
</sourcecode>
</section>
</section>

<section anchor="iana-considerations"><name>IANA Considerations</name>
<t>TODO</t>
</section>

<section anchor="internationalization-considerations"><name>Internationalization Considerations</name>
<t>TODO</t>
</section>

<section anchor="security-considerations"><name>Security Considerations</name>
<t>TODO</t>
</section>

<section anchor="acknowledgments"><name>Acknowledgments</name>
<t>TODO</t>
</section>

</middle>

<back>
<references><name>References</name>
<references><name>Normative References</name>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5730.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5731.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5732.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5733.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8259.xml"/>
</references>
<references><name>Informative References</name>
<reference anchor="XMLCOM-WEB" target="https://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html">
  <front>
    <title>Converting Between XML and JSON</title>
    <author>
      <organization>XML.com</organization>
    </author>
    <date year="2006"></date>
  </front>
</reference>
</references>
</references>

</back>

</rfc>
