<?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-core-02" submissionType="IETF" category="std" xml:lang="en" xmlns:xi="http://www.w3.org/2001/XInclude" indexInclude="true" tocDepth="4">

<front>
<title abbrev="RESTful Provisioning Protocol">RESTful Provisioning Protocol (RPP)</title><seriesInfo value="draft-wullink-rpp-core-02" 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 endpoints for the RESTful Provisioning Protocol, used for the provisioning and management of objects in a shared database.</t>
</abstract>

</front>

<middle>

<section anchor="introduction"><name>Introduction</name>
<t>This document describes an Application Programming Interface (API) API based on the HTTP protocol <xref target="RFC2616"></xref> and the principles of <xref target="REST"></xref>. Conforming to the REST constraints is generally referred to as being &quot;RESTful&quot;. Hence the API is dubbed: &quot;'RESTful Provisioning Protocol&quot; or &quot;RPP&quot; for short.</t>
<t>The RPP API is designed to be used for the provisioning and management of objects in a shared database, such as domain names, hosts, and entities.</t>
</section>

<section anchor="terminology"><name>Terminology</name>
<t>In this document the following terminology is used.</t>
<t>REST - Representational State Transfer (<xref target="REST"></xref>). An architectural style.</t>
<t>RESTful - A RESTful web service is a web service or API implemented using HTTP and the principles of <xref target="REST"></xref>.</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 or RPP - The protocol described in this document.</t>
<t>URL - A Uniform Resource Locator as defined in <xref target="RFC3986"></xref>.</t>
<t>Resource - An object having a type, data, and possible relationship to other resources, identified by a URL.</t>
<t>RPP client - An HTTP user agent performing an RPP request</t>
<t>RPP server - An HTTP server responsible for processing requests and returning results in any supported media type.</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>In examples, lines starting with &quot;C:&quot; represent data sent by a RPP client and lines starting with &quot;S:&quot; represent data returned by a RPP server. Indentation and white space in examples are provided only to illustrate element relationships and are not REQUIRED features of the protocol.</t>
<t>All example requests assume a RPP server using HTTP version 2 is listening on the standard HTTPS port on host rpp.example. An authorization token has been provided by an out of band process and MUST be used by the client to authenticate each request.</t>
</section>

<section anchor="request-headers"><name>Request Headers</name>
<t>A RPP request does not always require a request message body. The information conveyed by the HTTP method, URL, and request headers may be sufficient for the server to be able to successfully processes a request. However, the client MUST include a request message body when the server requires additional attributes to be present in the request message. The RPP HTTP headers listed below use the &quot;RPP-&quot; prefix, following the recommendations in <xref target="RFC6648"></xref>.</t>

<ul spacing="compact">
<li><tt>RPP-Cltrid</tt>:  The client transaction identifier is the equivalent of the <tt>clTRID</tt> element defined in <xref target="RFC5730"></xref> and MUST be used accordingly, when the HTTP message body does not contain an EPP request that includes a cltrid.</li>
<li><t><tt>RPP-Authorization</tt>: The client MAY use this header to send authorization information in the format <tt>&lt;method&gt; &lt;authorization information&gt;</tt>, similar to the HTTP <tt>Authorization</tt> header, defined in [RFC9110, Section 11.6.2]. The <tt>&lt;method&gt;</tt> indicates the type of authorization being used. For EPP object authorization information, for example the authorization information used for domain names described in [RFC5731, Section 2.3], a new <tt>authinfo</tt> method is defined and MUST be used. The <tt>&lt;authorization information&gt;</tt> defines the following comma separated fields:</t>

<ul spacing="compact">
<li>value (REQUIRED): Base64 encoded EPP password-based authorization information. Base64 encoding is used to prevent problems when special characters are present that may conflict with the format rules for the Authorization header.</li>
<li>roid (OPTIONAL): A Roid as defined in <xref target="RFC5731"></xref>, <xref target="RFC5733"></xref>, and <xref target="RFC5730"></xref>. The roid is used to identify the object for which the authorization information is provided. If the roid is not provided, then the server MUST assume that the authorization information is linked to the object identified by the URL of the request.</li>
</ul></li>
</ul>
<t>Use of the RPP-Authorization header:</t>

<sourcecode type="http"><![CDATA[RPP-Authorization: authinfo value=TXkgU2VjcmV0IFRva2Vu, roid=REG-XYZ-12345
]]>
</sourcecode>
<t>The value of the <tt>RPP-Authorization</tt> header is case sensitive. The server MUST reject requests where the case of the header value does not match the expected case.
The <tt>RPP-Authorization</tt> header is specific to the user agent and MUST NOT be cached, as recommended by <xref target="RFC9110" sectionFormat="bare" section="Section 16.4.2"></xref>, the server MUST use the correct HTTP cache directives to prevent caching of the <tt>RPP-Authorization</tt> header.</t>
</section>

<section anchor="response-headers"><name>Response Headers</name>
<t>The server HTTP response contains a status code, headers, and MAY contain an RPP response message in the message body. HTTP headers are used to transmit additional data to the client and MAY be used to send RPP process related data to the client. HTTP headers used by RPP MUST use the &quot;RPP-&quot; prefix, the following response headers have been defined for RPP.</t>

<ul>
<li><t><tt>RPP-Svtrid</tt>:  This header is the equivalent of the &quot;svTRID&quot; element defined in <xref target="RFC5730"></xref> and MUST be used accordingly when the RPP response does not contain an EPP response in the HTTP message body. If an HTTP message body with the EPP XML equivalent &quot;svTRID&quot; exists, both values MUST be consistent.</t>
</li>
<li><t><tt>RPP-Cltrid</tt>: This header is the equivalent of the &quot;clTRID&quot; element defined in <xref target="RFC5730"></xref> and MUST be used accordingly when the RPP response does not contain an EPP response in the HTTP message body. If the contents of the HTTP message body contains a &quot;clTRID&quot; value, then both values MUST be consistent.</t>
</li>
<li><t><tt>RPP-Code</tt>: This header is the equivalent of the EPP result code defined in <xref target="RFC5730"></xref> and MUST be used accordingly. This header MUST be added to all responses and MAY be used by the client for easy access to the result code, without having to parse the HTTP response message body.</t>
</li>
</ul>
<t>For the EPP codes related to session management (1500, 2500, 2501 and 2502) there are no corresponding RPP codes.</t>
<t>In order for RPP to be backwards compatible with EPP, RPP will use 5-digit coding of the result codes, where first digit will denote origin specification of the result codes.</t>
<t>For <xref target="RFC5730"></xref> Result Codes the leading digit MUST be &quot;0&quot;.
For RPP result codes the leading digit MUST be &quot;1&quot;. For avoidance of confusion RPP MUST not define new codes with the same semantic meaning as already defined in EPP.</t>
<t>For RPP codes the remaining 4 digits MUST keep the same semantics as <xref target="RFC5730"></xref> Result Codes.</t>

<ul spacing="compact">
<li><tt>RPP-Queue-Size</tt>: Return the number of unacknowledged messages in the client message queue. The server MAY include this header in all RPP responses.</li>
</ul>
</section>

<section anchor="error-handling-and-relation-between-http-status-codes-and-rpp-codes"><name>Error handling and relation between HTTP status codes and RPP codes</name>
<t>RPP leverages standard HTTP status codes to reflect the outcome of RPP operations. The RPP result codes are based on the EPP result codes defined in <xref target="RFC5730"></xref>. This allows clients to handle responses generically using common HTTP patterns. While the HTTP status code provides the primary, high-level outcome, the specific RPP result code MUST still be provided in the <tt>RPP-Code</tt> HTTP header for detailed diagnostics.</t>
<t>The mapping strategy is to use the most specific HTTP code that accurately reflects the operation's result.</t>
<t>For common and well-defined outcomes, a specific HTTP status code is used. For example, an attempt to access a non-existent resource (EPP code 2302) MUST return 404 Not Found, and an attempt to create a resource that already exists (EPP code 2303) MUST return 409 Conflict. This allows a client to handle these common situations based on the HTTP code alone.</t>
<t>For all other failures, a generic HTTP status code is used. Client-side errors (e.g., syntax, parameter, or policy violations) MUST return 400 Bad Request. Server-side failures MUST return 500 Internal Server Error.</t>
<t>The server MUST return HTTP status codes, following the mapping rules in Table 1.</t>
<t>Table 1: RPP result code and HTTP Status-Code mapping.</t>
<table>
<thead>
<tr>
<th>HTTP Status-Code</th>
<th>Description</th>
<th>Corresponding RPP result code(s)</th>
</tr>
</thead>

<tbody>
<tr>
<td>Success (2xx)</td>
<td></td>
<td></td>
</tr>

<tr>
<td>200 OK</td>
<td>The request was successful (e.g., for GET or UPDATE).</td>
<td>01000 (in all cases not specified otherwise),01300,01301</td>
</tr>

<tr>
<td>201 Created</td>
<td>The resource was created successfully.</td>
<td>01000 for resource creating requests (POST/PUT)</td>
</tr>

<tr>
<td>202 Accepted</td>
<td>The request was accepted for asynchronous processing.</td>
<td>01001</td>
</tr>

<tr>
<td>204 No Content</td>
<td>The resource was deleted successfully.</td>
<td>01000 for DELETE</td>
</tr>

<tr>
<td>Client Errors (4xx)</td>
<td></td>
<td></td>
</tr>

<tr>
<td>400 Bad Request</td>
<td>Generic client-side error (syntax, parameters, policy).</td>
<td>02000-02005,02104-02106,02300-02301,02304-02308</td>
</tr>

<tr>
<td>403 Forbidden</td>
<td>Authentication or authorization failed.</td>
<td>02200-02202</td>
</tr>

<tr>
<td>404 Not Found</td>
<td>The requested resource does not exist.</td>
<td>02303</td>
</tr>

<tr>
<td>409 Conflict</td>
<td>The resource could not be created because it already exists.</td>
<td>02302</td>
</tr>

<tr>
<td>Server Errors (5xx)</td>
<td></td>
<td></td>
</tr>

<tr>
<td>500 Internal Server Error</td>
<td>Generic server-side error; command failed.</td>
<td>02400</td>
</tr>

<tr>
<td>501 Not Implemented</td>
<td>The requested command or feature is not implemented.</td>
<td>02100-02103</td>
</tr>
</tbody>
</table><t>Some EPP result codes, like 01500, 02500, 02501 and 02502 are related to session management and therefore not applicable to a sessionless RPP protocol.</t>
</section>

<section anchor="endpoints"><name>Endpoints</name>
<t>Endpoints are described using URI Templates <xref target="RFC6570"></xref> relative to a discoverable base URL, as recommended by <xref target="RFC9205"></xref>. Some RPP endpoints do not require a request and/or response message.</t>
<t>The RPP endpoints are defined using the following URI Template syntax:</t>

<ul spacing="compact">
<li>{c}: An abbreviation for {collection}: this MUST be substituted with &quot;domains&quot;, &quot;hosts&quot;, &quot;entities&quot; or another collection of objects.</li>
<li>{i}: An abbreviation for an object identifier, this MUST be substituted with the value of a domain name, hostname, contact-id or a message-id or any other defined object.</li>
</ul>
<t>A RPP client MAY use the HTTP GET method for executing informational request only when no request data has to be added to the HTTP message body. Sending content using an HTTP GET request is discouraged in <xref target="RFC9110"></xref>, there exists no generally defined semantics for content received in a GET request. When an RPP object requires additional information, the client MUST use the HTTP POST method and add the query command content to the HTTP message body.</t>

<section anchor="availability-for-creation"><name>Availability for Creation</name>
<t>The Availability for Creation endpoint is used to check whether an object can be successfully provisioned. Two distinct methods are defined for checking the availability of provisioning of an object, the first method uses the HEAD method for a quick check to find out if the object can be provisioned. The second method uses the GET method to retrieve additional information about the object's availability for provisioning, for example about pricing or additional requirements to be able to provision the requested object.</t>
<t>When the client uses the HTTP HEAD method, the server MUST respond with an HTTP status code 200 (OK) if the object can be provisioned or with an HTTP status code 404 (Not Found) if the object cannot be provisioned.</t>
<t>When the client uses the HTTP GET method, the server MUST respond with an HTTP status code 200 (OK) if the object can be provisioned. The server MUST include a message body containing more detailed availability information, for example about pricing or additional requirements to be able to provision the requested object. The message body MAY be and empty JSON object if no additional information is applicable.</t>
<t>If the object cannot be provisioned then the server MUST return an HTTP status code 404 (Not Found) and include a problem statement in the message body.</t>
<t>As an extension point the server MAY define and the client MAY use additional HTTP query parameters to further specify the check operation or the kind of response information that shall be returned. For example Registry Fee Extension <xref target="RFC8748"></xref> defines a possibility to request certain currency, only certain commands or periods. Such functionality would add query parameters, which could be used with GET request to receive additional pricing information with the response. HEAD request would not be affected in this case.</t>
<t>The server MUST respond with the same HTTP status code if the same URL is requested with HEAD and with GET.</t>

<artwork><![CDATA[- Request: HEAD|GET {collection}/{id}/availability
- Request message: None
- Response message: Optional availability response
]]>
</artwork>
<t>Example request for a domain name that is not available for provisioning:</t>

<sourcecode type="http"><![CDATA[HEAD domains/foo.example/availability HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept-Language: en
RPP-Cltrid: ABC-12345

]]>
</sourcecode>
<t>Example response:</t>

<sourcecode type="http"><![CDATA[HTTP/2 404 Not Found
Date: Wed, 24 Jan 2024 12:00:00 UTC
Server: Example RPP server v1.0
RPP-Cltrid: ABC-12345
RPP-Svtrid: XYZ-12345
RPP-code: 01000
Content-Length: 0

]]>
</sourcecode>
</section>

<section anchor="resource-information"><name>Resource Information</name>
<t>The Object Info request MUST use the HTTP GET method on a resource identifying an object instance. If the object has authorization information attached then the client MUST use an empty message body and include the RPP-Authorization HTTP header. If the authorization is linked to a database object the client MUST also include the roid in the RPP-Authorization header. The client MAY also use a message body that includes the authorization information, the client MUST then not use the RPP-Authorization header.</t>

<ul spacing="compact">
<li>Request: GET {collection}/{id}</li>
<li>Request message: Optional</li>
<li>Response message: Info response</li>
</ul>
<t>Example request for an object not using authorization information.</t>

<sourcecode type="http"><![CDATA[GET domains/foo.example HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept: application/rpp+json
Accept-Language: en
RPP-Cltrid: ABC-12345

]]>
</sourcecode>
<t>Example request using RPP-Authorization header for an object that has attached authorization information.</t>

<sourcecode type="http"><![CDATA[GET domains/foo.example HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept: application/rpp+json
Accept-Language: en
RPP-Cltrid: ABC-12345
RPP-Authorization: authinfo value=TXkgU2VjcmV0IFRva2Vu

]]>
</sourcecode>
<t>Example Info response:</t>

<sourcecode type="http"><![CDATA[HTTP/2 200 OK
Date: Wed, 24 Jan 2024 12:00:00 UTC
Server: Example RPP server v1.0
Content-Length: 424
Content-Type: application/rpp+json
Content-Language: en
RPP-code: 01000

TODO: JSON message here
]]>
</sourcecode>
</section>

<section anchor="poll-for-messages"><name>Poll for Messages</name>
<t>The messages endpoint is used for retrieving messages stored on the server for the client to process.</t>

<ul spacing="compact">
<li>Request: GET /messages</li>
<li>Request message: None</li>
<li>Response message: Poll response</li>
</ul>
<t>The client MUST use the HTTP GET method on the messages resource collection to request the message at the head of the queue.</t>
<t>Example request:</t>

<sourcecode type="http"><![CDATA[GET messages HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept: application/rpp+json
Accept-Language: en
RPP-Cltrid: ABC-12345

]]>
</sourcecode>
<t>Example response:</t>

<sourcecode type="http"><![CDATA[HTTP/2 200 OK
Date: Wed, 24 Jan 2024 12:00:00 UTC
Server: Example RPP server v1.0
Content-Length: 312
Content-Type: application/rpp+json
Content-Language: en
RPP-code: 01301

TODO
]]>
</sourcecode>
</section>

<section anchor="delete-message"><name>Delete Message</name>

<ul spacing="compact">
<li>Request: DELETE /messages/{id}</li>
<li>Request message: None</li>
<li>Response message: Poll Ack response</li>
</ul>
<t>The client MUST use the HTTP DELETE method to acknowledge receipt of a message from the queue. The &quot;msgID&quot; attribute of a received RPP Poll message MUST be included in the message resource URL, using the {id} path element. The server MUST use RPP headers to return the RPP result code and the number of messages left in the queue. The server MUST NOT add content to the HTTP message body of a successful response, the server may add content to the message body of an error response.</t>
<t>Example request:</t>

<sourcecode type="http"><![CDATA[DELETE messages/12345 HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept: application/rpp+json
Accept-Language: en
RPP-Cltrid: ABC-12345

]]>
</sourcecode>
<t>Example response:</t>

<sourcecode type="http"><![CDATA[HTTP/2 200 OK
Date: Wed, 24 Jan 2024 12:00:00 UTC
Server: Example RPP server v1.0
Content-Language: en
RPP-code: 01000
RPP-Queue-Size: 0
RPP-Svtrid: XYZ-12345
RPP-Cltrid: ABC-12345
Content-Length: 145

TODO
]]>
</sourcecode>
</section>

<section anchor="create-resource"><name>Create Resource</name>

<ul spacing="compact">
<li>Request: POST {collection}</li>
<li>Request message: Object Create request</li>
<li>Response message: Object Create response</li>
</ul>
<t>The client MUST use the HTTP POST method to create a new object resource. If the RPP request results in a newly created object, then the server MUST return HTTP status code 200 (OK). The server MUST add the &quot;Location&quot; header to the response, the value of this header MUST be the URL for the newly created resource.</t>
<t>Example Domain Create request:</t>

<sourcecode type="http"><![CDATA[POST domains HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept: application/rpp+json
Content-Type: application/rpp+json
Accept-Language: en
Content-Length: 220

TODO
]]>
</sourcecode>
<t>Example Domain Create response:</t>

<sourcecode type="http"><![CDATA[HTTP/2 200
Date: Wed, 24 Jan 2024 12:00:00 UTC
Server: Example RPP server v1.0
Content-Language: en
Content-Length: 642
Content-Type: application/rpp+json
Location: https://rpp.example/domains/foo.example
RPP-code: 01000

TODO
]]>
</sourcecode>
</section>

<section anchor="delete-resource"><name>Delete Resource</name>

<ul spacing="compact">
<li>Request: DELETE {collection}/{id}</li>
<li>Request message: Optional</li>
<li>Response message: Status</li>
</ul>
<t>The client MUST the HTTP DELETE method and a resource identifying a unique object instance. The server MUST return HTTP status code 200 (OK) if the resource was deleted successfully.</t>
<t>Example Domain Delete request:</t>

<sourcecode type="http"><![CDATA[DELETE domains/foo.example HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept: application/rpp+json
Accept-Language: en
RPP-Cltrid: ABC-12345

]]>
</sourcecode>
<t>Example Domain Delete response:</t>

<sourcecode type="http"><![CDATA[HTTP/2 200 OK
Date: Wed, 24 Jan 2024 12:00:00 UTC
Server: Example RPP server v1.0
Content-Length: 80
RPP-Svtrid: XYZ-12345
RPP-Cltrid: ABC-12345
RPP-code: 01000

TODO
]]>
</sourcecode>
</section>

<section anchor="processes-path-segment"><name>Processes Path Segment</name>
<t>Each provisioning object may be related to one or more running processes, such as a transfer or deletion. Each process can have its own data, which is distinct from the data of the provisioning object itself. The processes can be started, stopped, or interacted with using their own specific set of representations and operations.</t>
<t>All processes related to a provisioning object in RPP MUST exist under the <tt>/{collection}/{id}/processes/{process_name}</tt> path.</t>
<t>The server operator MAY support direct access to process resources using server generated identifier. Such resource MAY be accessible using following URL: <tt>/{collection}/{id}/processes/{process_name}/{process_id}</tt>, where process_id is the process identifier.</t>
<t>A process MAY also expose a resource at <tt>/{collection}/{id}/processes/{process_name}/latest</tt> to access and interact with the latest process instance. In case server offers any access to process information of given process name, the access to the last instance using <tt>/{collection}/{id}/processes/{process_name}/latest</tt> URL is MANDATORY.</t>
<t>The server operator MAY decide which processes such resources exist for, whether they only exist for the currently running processes or also for completed or cancelled processes. The period for which completed processes remain available for retrieval is defined by server policy.</t>

<section anchor="generic-proces-interface"><name>Generic proces interface</name>
<t>A generic interface for interacting with the processes is defined as follows:</t>

<section anchor="starting"><name>Starting:</name>
<t><tt>POST /{collection}/{id}/processes/{process_name}</tt></t>
<t>The payload of such a request contains process-specific input information. A started process MAY create a resource to access and interact with the process instance. In such case the response MUST be a 201 Created with a <tt>Location</tt> header pointing to the created resource together with the process state representation. The created resource can be made accessible both using the <tt>latest</tt> mnemonic under a URL <tt>/{collection}/{id}/processes/{process_name}/latest</tt> or using a process id under a URL <tt>/{collection}/{id}/processes/{process_name}/{process_id}</tt>.</t>
<t>When a process is created, executed and immediately completed by the server, a 201 Created response MAY still be provided together with the representation of the process result.</t>
<t>Server MAY decide not to expose any resource for interaction with the created process, in such case a 200 OK MUST be provided.</t>
<t>Example:</t>

<sourcecode type="http"><![CDATA[POST /rpp/v1/domains/foo.example/processes/renewals HTTP/2
... other headers removed for bravity ...

{
    "duration": "P2Y"
}
]]>
</sourcecode>
</section>

<section anchor="cancelling"><name>Cancelling:</name>
<t>A client MAY use the &quot;latest&quot; mnemonic to cancel the latest process instance, in such case the request MUST be:</t>
<t><tt>DELETE /{collection}/{id}/processes/{process_name}/latest</tt></t>
<t>If the client wants to cancel a specific process instance, the request MUST be:</t>
<t><tt>DELETE /{collection}/{id}/processes/{process_name}/{process_id}</tt></t>
<t>This request is intended to stop the running process. The server MUST return a 204 response if the process has been stopped and the resource is gone, or a 200 response if the process has been stopped but the resource remains.</t>
</section>

<section anchor="status"><name>Status</name>
<t>A client MAY use the &quot;latest&quot; mnemonic to request the latest process instance, in such case the request MUST be:</t>
<t><tt>GET /{collection}/{id}/processes/{process_name}/latest</tt></t>
<t>If the client wants to retrieve data of a specific process instance, the request MUST be:</t>
<t><tt>GET /{collection}/{id}/processes/{process_name}/{process_id}</tt></t>
<t>The request retrieves the representation of the task status. If no task is running, the server MAY return the status of the completed task or return a 404 response.</t>
</section>

<section anchor="other-operations"><name>Other operations</name>
<t>Other operations on a process can be performed by adding path segments to the <tt>/{collection}/{id}/processes/{process_name}/latest</tt> or <tt>/{collection}/{id}/processes/{process_name}/{process_id}</tt> URL path.</t>
</section>

<section anchor="listing"><name>Listing</name>
<t>A server MAY implement a listing facility for some or all, current or past processes.</t>
<t>The following URL structure and HTTP method MAY be exposed by the server and MUST be used by the client to retrieve process list filtered by process name:</t>
<t><tt>GET /{collection}/{id}/processes/{process_name}/</tt></t>
<t>The following URL structure and HTTP method MAY be exposed by the server and MUST be used by the client to retrieve full process list independent of the process name:</t>
<t><tt>GET /{collection}/{id}/processes/</tt></t>
<t>It is up to server policy to define the type of processes and state, running or completed, made available for the client. A server MAY also choose not implement this end point at all returning either the HTPP status code 404 Not Found or a 501 Not Implemented status code.</t>
</section>
</section>

<section anchor="relation-to-object-representation"><name>Relation to object representation</name>
<t>In certain situations a resource creation may require additional process data or implicitly start an asynchronous process with own inputs, lifecycle and state. In these cases, the representation sent to the server MAY contain a combination of object data and process-related data. For example a domain create request contains domain representation data which will be stored with domain object, and domain creation process data such as registration duration or price, which would be part as registration process data, but not directly stored with the domain object.</t>
<t>For the process data in the message body to be distinct and consistent with the URL path structure, it MUST be enclosed in the <tt>processes/{process_name}</tt> JSON path when transmitted with the object's representation.</t>
<t>Structure:</t>

<sourcecode type="http"><![CDATA[POST /.../{collection}/{id}
...
{
    ... object data ...
    "processes": {
        "{process_name}": {
            ... process data ...
        }
    }
    ...
}
]]>
</sourcecode>
<t>Example: Domain Create request with 2-year registration:</t>

<sourcecode type="http"><![CDATA[POST /rpp/v1/domains HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept: application/rpp+json
Content-Type: application/rpp+json
Accept-Language: en
Content-Length: 220

{
    "name": "foo.example",
    "processes": {
        "creation": {
            "periods": "P2Y"
        }
    }
    ... other domain data ...
}
]]>
</sourcecode>
</section>
</section>

<section anchor="renew-resource"><name>Renew Resource</name>

<ul spacing="compact">
<li>Request: POST /{collection}/{id}/processes/renewals</li>
<li>Request message: Renew request</li>
<li>Response message: Renew response</li>
</ul>
<t>Not every object resource includes support for the renew command. The response MUST include the Location header for the created renewal process resource.</t>
<t>Example Domain Renew request:</t>

<sourcecode type="http"><![CDATA[POST /rpp/v1/domains/foo.example/processes/renewals HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept: application/rpp+json
Content-Type: application/rpp+json
RPP-Cltrid: ABC-12345
Accept-Language: en
Content-Length: 210

TODO: add renew request data here
]]>
</sourcecode>
<t>Example Renew response:</t>

<sourcecode type="http"><![CDATA[HTTP/2 200 OK
Date: Wed, 24 Jan 2024 12:00:00 UTC
Server: Example RPP server v1.0
Content-Language: en
RPP-Svtrid: XYZ-12345
RPP-Cltrid: ABC-12345
Content-Length: 205
Location: https://rpp.example/rpp/v1/domains/foo.example/processes/renewals/XYZ-12345
Content-Type: application/rpp+json
RPP-code: 01000

TODO add renew response data here
]]>
</sourcecode>
</section>

<section anchor="transfer-resource"><name>Transfer Resource</name>
<t>The Transfer command is mapped to a nested resource, named &quot;transfer&quot;. The semantics of the HTTP DELETE method are determined by the role of the client executing the DELETE method. The DELETE method is defined as &quot;reject transfer&quot; for the current sponsoring client of the object. For the new sponsoring client the DELETE method is defined as &quot;cancel transfer&quot;.</t>

<section anchor="start"><name>Start</name>

<ul spacing="compact">
<li>Request: POST /{collection}/{id}/processes/transfers</li>
<li>Request message: Optional</li>
<li>Response message: Status</li>
</ul>
<t>In order to initiate a new object transfer process, the client MUST use the HTTP POST method on a unique resource to create a new transfer resource object. Not all RPP objects support the Transfer command.</t>
<t>If the transfer request is successful, then the response MUST include the Location header for the object being transferred.</t>
<t>Example request not using object authorization:</t>

<sourcecode type="http"><![CDATA[POST /rpp/v1/domains/foo.example/processes/transfers HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept: application/rpp+json
Accept-Language: en
RPP-Cltrid: ABC-12345
Content-Length: 0

]]>
</sourcecode>
<t>Example request using object authorization:</t>

<sourcecode type="http"><![CDATA[POST /rpp/v1/domains/foo.example/processes/transfers HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept: application/rpp+json
RPP-Cltrid: ABC-12345
RPP-Authorization: authinfo value=TXkgU2VjcmV0IFRva2Vu
Accept-Language: en
Content-Length: 0

]]>
</sourcecode>
<t>Example request using 1 year renewal period, using the <tt>unit</tt> and <tt>value</tt> query parameters:</t>

<sourcecode type="http"><![CDATA[POST /rpp/v1/domains/foo.example/processes/transfers HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept: application/rpp+json
Accept-Language: en
RPP-Cltrid: ABC-12345
Content-Length: 23

{
  "duration": "P2Y"
}
]]>
</sourcecode>
<t>Example Transfer response:</t>

<sourcecode type="http"><![CDATA[HTTP/2 200 OK
Date: Wed, 24 Jan 2024 12:00:00 UTC
Server: Example RPP server v1.0
Content-Language: en
Content-Length: 182
Content-Type: application/rpp+json
Location: https://rpp.example/rpp/v1/domains/foo.example/processes/transfers/latest
RPP-code: 01001

{
  "trStatus": "pending",
  "reID": "ClientX",
  "acID": "ClientY",
  "reDate": "2000-06-06T22:00:00.0Z",
  "acDate": "2000-06-11T22:00:00.0Z",
  "exDate": "2002-09-08T22:00:00.0Z
}
]]>
</sourcecode>
</section>

<section anchor="status-1"><name>Status</name>
<t>A transfer object may not exist, when no transfer has been initiated for the specified object.
The client MUST use the HTTP GET method and MUST NOT add content to the HTTP message body.</t>

<ul spacing="compact">
<li>Request: GET {collection}/{id}/processes/transfers</li>
<li>Request message: Optional</li>
<li>Response message: Transfer Status response</li>
</ul>
<t>Example domain name Transfer Status request without authorization information required:</t>

<sourcecode type="http"><![CDATA[GET /rpp/v1/domains/foo.example/processes/transfers HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept: application/rpp+json
Accept-Language: en
RPP-Cltrid: ABC-12345

]]>
</sourcecode>
<t>If the requested transfer object has associated authorization information that is not linked to another database object, then the HTTP GET method MUST be used and the authorization information MUST be included using the RPP-Authorization header.</t>
<t>Example domain name Transfer Query request using RPP-Authorization header:</t>

<sourcecode type="http"><![CDATA[GET /rpp/v1/domains/foo.example/processes/transfers HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept: application/rpp+json
Accept-Language: en
RPP-Cltrid: ABC-12345
RPP-Authorization: authinfo value=TXkgU2VjcmV0IFRva2Vu

]]>
</sourcecode>
<t>If the requested object has associated authorization information linked to another database object, then the HTTP GET method MUST be used and the RPP-Authorization header MUST be included.</t>
<t>Example domain name Transfer Query request and authorization using RPP-Authorization header:</t>

<sourcecode type="http"><![CDATA[GET /rpp/v1/domains/foo.example/processes/transfers HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept: application/rpp+json
Accept-Language: en
RPP-Authorization: authinfo value=TXkgU2VjcmV0IFRva2Vu
Content-Length: 0

]]>
</sourcecode>
<t>Example Transfer Query response:</t>

<sourcecode type="http"><![CDATA[HTTP/2 200 OK
Date: Wed, 24 Jan 2024 12:00:00 UTC
Server: Example RPP server v1.0
Content-Length: 230
Content-Type: application/rpp+json
Content-Language: en
RPP-code: 01000

TODO
]]>
</sourcecode>
</section>

<section anchor="cancel"><name>Cancel</name>

<ul spacing="compact">
<li>Request: POST /{collection}/{id}/processes/transfers/cancelation</li>
<li>Request message: Optional</li>
<li>Response message: Status</li>
</ul>
<t>The new sponsoring client MUST use the HTTP POST method to cancel a requested transfer.</t>
<t>Example request:</t>

<sourcecode type="http"><![CDATA[POST /rpp/v1/domains/foo.example/processes/transfers/cancelation HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept: application/rpp+json
Accept-Language: en
RPP-Cltrid: ABC-12345

]]>
</sourcecode>
<t>Example response:</t>

<sourcecode type="http"><![CDATA[HTTP/2 200 OK
Date: Wed, 24 Jan 2024 12:00:00 UTC
Server: Example RPP server v1.0
Content-Length: 80
RPP-Svtrid: XYZ-12345
RPP-Cltrid: ABC-12345
RPP-code: 01000

TODO
]]>
</sourcecode>
</section>

<section anchor="reject"><name>Reject</name>

<ul spacing="compact">
<li>Request: POST /{collection}/{id}/processes/transfers/rejection</li>
<li>Request message:  None</li>
<li>Response message: Status</li>
</ul>
<t>The currently sponsoring client of the object MUST use the HTTP POST method to reject a started transfer process.</t>
<t>Example request:</t>

<sourcecode type="http"><![CDATA[POST /rpp/v1/domains/foo.example/processes/transfers/rejection HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept: application/rpp+json
Accept-Language: en
RPP-Cltrid: ABC-12345

]]>
</sourcecode>
<t>Example Reject response:</t>

<sourcecode type="http"><![CDATA[HTTP/2 200 OK
Date: Wed, 24 Jan 2024 12:00:00 UTC
Server: Example RPP server v1.0
Content-Length: 80
RPP-Svtrid: XYZ-12345
RPP-Cltrid: ABC-12345
RPP-code: 01000

TODO

]]>
</sourcecode>
</section>

<section anchor="approve"><name>Approve</name>

<ul spacing="compact">
<li>Request: POST /{collection}/{id}/processes/transfers/approval</li>
<li>Request message: Optional</li>
<li>Response message: Status</li>
</ul>
<t>The currently sponsoring client MUST use the HTTP POST method to approve a transfer requested by the new sponsoring client.</t>
<t>Example Approve request:</t>

<sourcecode type="http"><![CDATA[POST /rpp/v1/domains/foo.example/processes/transfers/approval HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept: application/rpp+json
Accept-Language: en
RPP-Cltrid: ABC-12345
Content-Length: 0

]]>
</sourcecode>
<t>Example Approve response:</t>

<sourcecode type="http"><![CDATA[HTTP/2 200 OK
Date: Wed, 24 Jan 2024 12:00:00 UTC
Server: Example RPP server v1.0
Content-Length: 80
RPP-Svtrid: XYZ-12345
RPP-Cltrid: ABC-12345
RPP-code: 01000

TODO
]]>
</sourcecode>
</section>
</section>

<section anchor="update-resource"><name>Update Resource</name>

<ul spacing="compact">
<li>Request: PATCH {collection}/{id}</li>
<li>Request message: Object Update message</li>
<li>Response message: Status</li>
</ul>
<t>An object Update request MUST be performed using the HTTP PATCH method. The request message body MUST contain an Update message.</t>
<t><strong>TODO:</strong> when using JSON, also allow for JSON patch so client can send partial update data only?</t>
<t>Example request:</t>

<sourcecode type="http"><![CDATA[PATCH domains/foo.example HTTP/2
Host: rpp.example
Authorization: Bearer <token>
Accept: application/rpp+json
Content-Type: application/rpp+json
Accept-Language: en
Content-Length: 252

TODO
]]>
</sourcecode>
<t>Example response:</t>

<sourcecode type="http"><![CDATA[HTTP/2 200 OK
Date: Wed, 24 Jan 2024 12:00:00 UTC
Server: Example RPP server v1.0
Content-Length: 80
RPP-Svtrid: XYZ-12345
RPP-Cltrid: ABC-12345
RPP-code: 01000

TODO
]]>
</sourcecode>
</section>
</section>

<section anchor="extension-framework"><name>Extension Framework</name>
<t>TODO</t>
</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>RPP relies on the security of the underlying HTTP <xref target="RFC9110"></xref> transport, hence the best common practices for securing HTTP also apply to RPP. It is RECOMMENDED to follow them closely.</t>
<t>Data confidentiality and integrity MUST be enforced, all data transport between a client and server MUST be encrypted using TLS <xref target="RFC5246"></xref>. <xref target="RFC5734" sectionFormat="bare" section="Section 9"></xref> describes the level of security that is REQUIRED for all RPP endpoints.</t>
<t>Due to the stateless nature of RPP, the client MUST include the authentication credentials in each HTTP request. This MAY be done by using JSON Web Tokens (JWT) <xref target="RFC7519"></xref> or Basic authentication <xref target="RFC7617"></xref>.</t>
</section>

<section anchor="change-history"><name>Change History</name>

<section anchor="version-01-to-02"><name>Version 01 to 02</name>

<ul spacing="compact">
<li>Updated the examples, changed from &quot;<em>.example.org&quot; to &quot;</em>.example&quot;</li>
<li>Merged the RPP-EPP-Code and RPP-Code headers into a single RPP-Code header</li>
<li>Update the RPP-Authorization header to match the HTTP Authorization header format</li>
<li>Added new process path segment and process representations</li>
<li>Added use of Problem Detail <xref target="RFC9457"></xref> for error responses</li>
<li>Updated the Check request to now use an &quot;availability&quot; path segment and support both GET and HEAD methods</li>
</ul>
</section>

<section anchor="version-00-to-01"><name>Version 00 to 01</name>

<ul spacing="compact">
<li>Updated &quot;Request Headers&quot; and &quot;Response Headers&quot; section</li>
<li>Changed transfer resource URL and HTTP method for reject, approve and cancel, in order to make the API easier to use</li>
</ul>
</section>

<section anchor="version-00-draft-rpp-core-to-00-draft-wullink-rpp-core"><name>Version 00 (draft-rpp-core) to 00 (draft-wullink-rpp-core)</name>

<ul spacing="compact">
<li>Renamed the document name to &quot;draft-wullink-rpp-core&quot;</li>
<li>Removed sections: Design Considerations, Resource Naming Convention, Session Management, HTTP Layer, Content Negotiation, Object Filtering, Error Handling</li>
<li>Renamed Commands section to Endpoints</li>
<li>Removed text about extensions</li>
<li>Changed naming to be less EPP like and more RDAP like</li>
</ul>
</section>
</section>

</middle>

<back>
<references><name>References</name>
<references><name>Normative References</name>
<reference anchor="REST" target="http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm">
  <front>
    <title>Architectural Styles and the Design of Network-based Software Architectures</title>
    <author fullname="Roy Fielding" initials="R." surname="Fielding">
      <organization></organization>
    </author>
    <date year="2000"></date>
  </front>
</reference>
<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.2616.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3986.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5246.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.5734.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6570.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6648.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7519.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7617.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9110.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9205.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9457.xml"/>
</references>
<references><name>Informative References</name>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8748.xml"/>
</references>
</references>

</back>

</rfc>
