Helpful Howto for EPP registrars

Ver 0.1.3 -- Sept 28, 2001

Document Overview

This document is intended to aid registrars who are just starting out with EPP.   Whether you are new to the domain name registrar scene, or if you are growing your domain name registration portfolio with an EPP registry (eg. .name, .info, .pro, .biz, etc...), this document should give you the necessary help to get started.  For those registrars who already have experience with RRP (eg. Verisign's com/net/org registry), this document contains helpful hints and EPP/RRP comparisons.

General EPP Overview

There are two majors aspects to EPP:  objects and actions.  Objects are entities stored in the EPP registry, such as domains, contacts and hosts (aka "nameservers").  Actions affect changes to the registry and the objects it contains (eg. check, create, update, delete...).  EPP registries and registrars communicate via messages in XML format.  XML conveniently organizes data in requests and responses into logical groups and hierarchies.  Because of the way the protocol is defined, it is transport independant.  This means that a registry may offer any number of transport layers to carry the EPP message (eg. plain TCP, TCP+TLS, SMTP, BEEP, ...).  EPP is also easily extensible.  Registries, depending their own or their domain's business needs, may define additional object type or actions, or even additional payload data for existing messages.

Basic things you can do with EPP

In the arena of domain names, the most obvious is registering domains.  As explained earlier, EPP defines three main object types:  domains, contacts and hosts.  It also defines a core set of actions (some of which are not applicable to all object types): check, info, create, update, delete, transfer and renew.

For those of you who come from an RRP background, this chart draws a parallel between RRP and EPP:

    EPP                     RRP

    domain                  domain
    host                    nameserver
    contact                 <new>
    check                   check
    info                    status
    create                  add
    update                  mod
    delete                  del
    transfer                transfer
    renew                   renew

Outside of the realm of objects, EPP defines the following requests:  login, logout, hello, and poll.  Login and logout should be pretty self-explanatory:  they allow a registrar to establish a persistent connection to an EPP registry.  The "hello" request allows a registrar to solicit a greeting from the registry (the greeting will be explained more a little later).  The poll action is the mechanism by which a registrar can retrieve notifications from the registry, such as object transfer-away notifications.

The greeting is used by an EPP registry to let the registrar know which services and options it offers.  In a connection-oriented session, the greeting is spontaneously sent by the registry when the registrar connects.   In a connectionless session (eg SMTP), the registrar must expressly ask for a greeting by sending the "hello" command.  This command can also be used in connection-oriented sessions, although the services offered since the greeting was sent should not have changed.

EPP allows for two types of sessions:  persistent and stateless.  In a persistent session, the registrar establishes a connection (e.g. over a TCP socket) and issues the login command before any other request.  The login contains the registrar’s client id, password (and optionally a new password), preferred language, preferred protocol version and a list of services which the registrar wishes to use.  An EPP registry could reject a login from a registrar for a number of reasons.  Those include:

Note that providing a new password in a login is the only way the registrar can change its password through EPP.

Here is an example of the login command where the registrar wishes to use domain, contact and host services:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <epp xmlns="urn:iana:xml:ns:epp-1.0" xmlns:xsi="" xsi:schemaLocation="urn:iana:xml:ns:epp-1.0 epp-1.0.xsd"> <command> <creds> <clID>ClientX</clID> <pw>foo-BAR2</pw> <newPW>bar-FOO2</newPW> <options> <version>1.0</version> <lang>en</lang> </options> </creds> <login> <svcs> <domain:svc xmlns:domain="urn:iana:xml:ns:domain" xsi:schemaLocation="urn:iana:xml:ns:domain domain.xsd"/> <contact:svc xmlns:contact="urn:iana:xml:ns:contact" xsi:schemaLocation="urn:iana:xml:ns:contact contact.xsd"/> <host:svc xmlns:host="urn:iana:xml:ns:host" xsi:schemaLocation="urn:iana:xml:ns:host host.xsd"/> </svcs> </login> <unspec/> <clTRID>ABC-12345</clTRID> </command> </epp>

Notice that the “creds” (i.e. credentials) are contained outside of the login tag.  This is what facilitates stateless sessions.  Once a registrar is logged in, the creds must not be present in any further commands, inluding the logout.  In a stateless session, the registrar must specify the creds at each command.  If a registrar is using a connection-oriented transport (e.g. a TCP socket), it is recommended that a persistent session be used.  This is usually more efficient because the server doesn’t have to validate the client id and password at each command.  Some registrars might only allow persistent sessions over connection-oriented transports.  Note that it is more efficient to maintain the same connection and session for as long as possible.  As many registries require secure, encrypted communications, the “handshake” portion of the connection can be resource intensive.   Repeating the steps of connecting, logging in, sending a single command, logging out, and disconnecting would be very costly to the registrar and the registry.  If the registrar is using a connectionless transport (e.g. SMTP), then a stateless session must be used and the login and logout commands are not valid and will be rejected.

In every EPP command, there are two other optional command elements:  unspec and clTRID.  The latter is pretty simple.  It is a client transaction identifier holder.  The registrar may use it to track requests for logging or auditing.  The clTRID, if supplied, is returned along with the svTRID (server transaction identifier) in the response to an EPP command.  In the response, they are both wrapped in the trID tag.   It is highly recommended that the registrar use the clTRID for every “transform” action (i.e. create, delete, update, transfer, renew).  The registrar may optionally use the clTRID in query actions, but because these actions don’t normally incur a charge to the registrar, transaction tracing and tracking is not as critical.

The unspec tag is a little more complex.  It can be present in both EPP requests and responses.  It is a placeholder for registry-specific extensions to EPP.  For instance, the .info registry, during its Sunrise Registration Period, was using the unspec tag to hold the domain trademark data in create, info and update commands.  The registrar should contact their registry operator to determine if there are any unspec extensions that must be used in interactions with the registry.

Now, let's look at few typical tasks that a registrar would want to perform.   We'll describe the commands and the required data for those commands.

The Nitty-Gritty

Domain Registration: Domain Create

Being at the core of a domain registrar's functionality, we'll start with this one.  Actually, we'll start with a step a registrar should perform before issuing a domain create action.  To not waste precious time of the registrant, there is a command to allow the registrar to check if a domain name is available before actually submitting a registration for it.   EPP offers this in the domain check action.  This command actually allows a list of domains to be checked.  The command is as follows:

(A note for these XML examples:  the namespace specifications for these commands might vary depending on the version of EPP the registry is using.  Please see the section at the end of document regarding EPP versions.)

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <epp xmlns="urn:iana:xml:ns:epp-1.0" xmlns:xsi="" xsi:schemaLocation="urn:iana:xml:ns:epp-1.0 epp-1.0.xsd"> <command> <check> <domain:check xmlns:domain="urn:iana:xml:ns:domain-1.0" xsi:schemaLocation="urn:iana:xml:ns:domain-1.0 domain-1.0.xsd"> <domain:name>example1.tld</domain:name> <domain:name>example2.tld</domain:name> <domain:name>example3.tld</domain:name> </domain:check> </check> <unspec/> <clTRID>ABC-12346</clTRID> </command> </epp>

The response will contain the same list of domains (though not necessarily in the same order) with indicators to say whether the registry knows of this domain or not.

Here is a typical response:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <epp xmlns="urn:iana:xml:ns:epp-1.0" xmlns:xsi="" xsi:schemaLocation="urn:iana:xml:ns:epp-1.0 epp-1.0.xsd"> <response> <result code=?1000?> <msg>Command completed successfully</msg> </result> <resData> <domain:chkData xmlns:domain="urn:iana:xml:ns:domain-1.0" xsi:schemaLocation="urn:iana:xml:ns:domain-1.0 domain-1.0.xsd"> <domain:cd x="+">example1.tld</domain:cd> <domain:cd x="-">example2.tld</domain:cd> <domain:cd x="+">example3.tld</domain:cd> </domain:chkData> </resData> <unspec/> <trID> <clTRID>ABC-12346</clTRID> <svTRID>54322-XYZ</svTRID> </trID> </response> </epp>

The “+” sign indicates that the domain exists in the registry.   The “-” sign, then logically, means that the domain does not exist in the registry and is available for registration.

If a domain is available for registration, then the registrar can continue with the domain create command.  With all of the optional data defined by EPP, this command is one of the simplest.  All it requires is the name of the domain to create and the authorization information for the new domain.  Authorization Information (or simply "auth info") is a passphrase a registrar asks of its registrant when creating a domain or a contact.  This passphrase is used by the registrant to authorize a transfer of the object to another registrar.  A reminder for RRP graduates, this command equates to "add domain".

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <epp xmlns="urn:iana:xml:ns:epp-1.0" xmlns:xsi="" xsi:schemaLocation="urn:iana:xml:ns:epp-1.0 epp-1.0.xsd"> <command> <create> <domain:create xmlns:domain="urn:iana:xml:ns:domain-1.0" xsi:schemaLocation="urn:iana:xml:ns:domain-1.0 domain-1.0.xsd"> <domain:name>example.tld</domain:name> <domain:authInfo type="pw">2fooBAR</domain:authInfo> </domain:create> </create> <unspec/> <clTRID>ABC-12345</clTRID> </command> </epp>

Now, unfortunately, sometimes this command might not always be this simple.   First, without specifying a period of activity for the domain, the registry will apply its default, which might or might not be 1 year.  It's always best to specify a period so that there’s no ambiguity and no surprise if the default value is not what was expected.

Second, some registries might impose that some of the optional data is required.  The .info registry, for example, requires 2 nameservers, a registrant contact and at least three other contacts, one for each type (admin, billing, and tech).  So it's very likely that you might have to specify other commands before the domain create.  Let's move on for the moment to the creation of other EPP objects.

Contact Creation

EPP is designed for thick registry operators who require contact information for centralized whois services.  Therefore, an EPP registrar is allowed to create contact objects in the registry and associate them to domains.  Contact object maintenance is the most complicated part of EPP.  Once you've mastered it, the rest is easy.

To create a contact, a registrar must collect the following information from the registrant (optional items are marked with a '*'):  name, organization*, postal address (street (up to three), city, state/province*, postal code* and country), voice phone number*, fax phone number* and email address.  Now, because of the demands of a multilingual world, the postal address of a contact can be specified in UTF-8 encoding (note that some registries might not support this).  EPP requires that there be at least an ASCII 7-bit version provided.  This is for more legacy uses, such as traditional whois.

Ok, so, the contact create command goes something like this:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <epp xmlns="urn:iana:xml:ns:epp-1.0" xmlns:xsi="" xsi:schemaLocation="urn:iana:xml:ns:epp-1.0 epp-1.0.xsd"> <command> <create> <contact:create xmlns:contact="urn:iana:xml:ns:contact-1.0" xsi:schemaLocation="urn:iana:xml:ns:contact-1.0 contact-1.0.xsd"> <contact:id>sh8013</contact:id> <contact:ascii> <contact:name>John Doe</contact:name> <contact:org>Example Inc.</contact:org> <contact:addr> <contact:street>123 Example Dr.</contact:street> <contact:street>Suite 100</contact:street> <contact:city>Dulles</contact:city> <contact:sp>VA</contact:sp> <contact:pc>20166-6503</contact:pc> <contact:cc>US</contact:cc> </contact:addr> </contact:ascii> <contact:voice x="1234">+1.7035555555</contact:voice> <contact:fax>+1.7035555556</contact:fax> <contact:email></contact:email> <contact:authInfo type="pw">2fooBAR</contact:authInfo> </contact:create> </create> <unspec/> <clTRID>ABC-12345</clTRID> </command> </epp>

Now, watch out.  Depending on the version of EPP which the registry is using, you may or may not have to specify a contact id on contact creation.   At the time of this writing, the .info registry is/was using a version of EPP where you don't specify the contact id.  The response to the contact creation will return the newly-created Repository Object Identifier.   This “ROID” will identify the contact object in associations with domain objects.  In newer versions of the protocol, the registrar-specified contact id is used.

The contact create example above only shows the inclusing of the 7-bit ASCII address in the “contact:ascii” tag.  This information is mandatory (although some elements in the address are optional).  There is an additional and optional address tag called “contact:i15d”.   The “i15d” is short for “internationalized” (starts with i ends with d with 15 characters between them. Clever, huh?).   This tag can contain the contact’s address with UTF-8 characters.

The sp, pc and cc tags in the address contain the state/province, postal code and country code, respectively.  The country code must be specified using the standard ISO country code listing.  And, yes, it currently does not include “UK” (among other countries).  “GB” should be used in its place.

Once the contact is created, the object identifier can be used in associations with domain objects.  Domains can have a single registrant contact.  They can also have any number of administrative, billing and technical contacts.  Let's put this aside for a moment and take a look at nameserver creation.

Host (aka "Nameserver") Creation

Nameserver creation is pretty simple.  There are two types of nameservers:   those that belong to the TLD(s) that are authoritative to the registry and those that don't (i.e. "foreign nameservers").  The difference between the two is the nameservers that are outside of the authoritative TLD(s) of the registry don't get IPs in the registry.  The idea is that only the authoritative registry for the nameserver's domain should know the nameserver's IP address(es).  The native nameservers can have up to 13 addresses (a limit imposed by many, if not most, registries).  IP addresses in EPP come in two forms:  IPv4 and IPv6.  Note that some registries might not allow IPv6.  Also note that the EPP registry may prohibit certain IP ranges from being used.  Check the EPP Host spec or with your registrar for those ranges, but those are usually the ones that haven’t been allocated for public use by IANA.

The host create command:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <epp xmlns="urn:iana:xml:ns:epp-1.0" xmlns:xsi="" xsi:schemaLocation="urn:iana:xml:ns:epp-1.0 epp-1.0.xsd"> <command> <create> <host:create xmlns:host="urn:iana:xml:ns:host-1.0" xsi:schemaLocation="urn:iana:xml:ns:host-1.0 host-1.0.xsd"> <host:name>ns1.example.tld</host:name> <host:addr ip="v4"></host:addr> <host:addr ip="v4"></host:addr> <host:addr ip="v6">1080:0:0:0:8:800:200C:417A</host:addr> <host:addr ip="v6">::FFFF:</host:addr> </host:create> </create> <unspec/> <clTRID>ABC-12345</clTRID> </command> </epp>

Notice that you can mix and match IP address types for a single host.

That's it.  Pretty simple, huh?

Domain Create (con't)

Now, let's get back to the domain creation.  Here it is with contacts, nameservers and the period specified:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <epp xmlns="urn:iana:xml:ns:epp-1.0" xmlns:xsi="" xsi:schemaLocation="urn:iana:xml:ns:epp-1.0 epp-1.0.xsd"> <command> <create> <domain:create xmlns:domain="urn:iana:xml:ns:domain-1.0" xsi:schemaLocation="urn:iana:xml:ns:domain-1.0 domain-1.0.xsd"> <domain:name>example.tld</domain:name> <domain:period unit="y">2</domain:period> <domain:ns>ns1.another-domain.tld</domain:ns> <domain:ns>ns2.another-domain.tld</domain:ns> <domain:registrant>jd1234</domain:registrant> <domain:contact type="admin">sh8013</domain:contact> <domain:contact type="tech">sh8013</domain:contact> <domain:authInfo type="pw">2fooBAR</domain:authInfo> </domain:create> </create> <unspec/> <clTRID>ABC-12345</clTRID> </command> </epp>

Notice that the same contact id is being used for both the admin and tech contact types.  That contact id could have also been used for the registrant.  Also take notice that the nameservers for this new domain are not using the same domain name.  EPP registries will not implicitly create nameservers in the same domain namespace upon creation of the domain.   That's because native nameserver require at least 1 IP address, which can’t be specified in the domain create command.  Note that the order of the nameserver is not significant in DNS resolution of the domain.   This order is not necessarily preserved in the "domain info" response.

Querying existing objects: the INFO command

Once an object is in the EPP registry, a registrar may retrieve information regarding the object.  This is achieved through the "info" command.  The info request for any of the currently known EPP objects is very simple.   All that is required is the object identifier.  For domains and nameservers, this is the fully qualified name of the object (i.e. the domain's name or the nameserver's name).  For contacts, this is either the contact's ROID that was returned by the creation of the object or the contact id that was provided by the registrar in the contact create request.  This depends on the version of EPP that the registry is using.  For RRP users, "info" is synonymous with the "status" command.  The major difference is that, in RRP, only the current sponsoring registrar is permitted to use the status command on a domain or nameserver.  In EPP, all registrars are permitted to use the info command for all objects.  Registry policy defines what is viewable by registrars using info.  Typically, only the current sponsoring registrar is returned the object’s auth info in the response from the server.  This protects the object from malicious transfer requests, since the auth info is required by the registrar requesting the transfer.

To provide a typical example of usage, here is a domain info request.

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <epp xmlns="urn:iana:xml:ns:epp-1.0" xmlns:xsi="" xsi:schemaLocation="urn:iana:xml:ns:epp-1.0 epp-1.0.xsd"> <command> <info> <domain:info xmlns:domain="urn:iana:xml:ns:domain-1.0" xsi:schemaLocation="urn:iana:xml:ns:domain-1.0 domain-1.0.xsd"> <domain:name>example.tld</domain:name> </domain:info> </info> <unspec/> <clTRID>ABC-12346</clTRID> </command> </epp>

The server's response to this request could be something like this:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <epp xmlns="urn:iana:xml:ns:epp-1.0" xmlns:xsi="" xsi:schemaLocation="urn:iana:xml:ns:epp-1.0 epp-1.0.xsd"> <response> <result code="1000"> <msg>Command completed successfully</msg> </result> <resData> <domain:infData xmlns:domain="urn:iana:xml:ns:domain-1.0" xsi:schemaLocation="urn:iana:xml:ns:domain-1.0 domain-1.0.xsd"> <domain:name>example.tld</domain:name> <domain:roid>EXAMPLE1-VRSN</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>ns1.example.tld</domain:ns> <domain:ns>ns2.example.tld</domain:ns> <domain:ns>ns1.backup.tld</domain:ns> <domain:host>ns1.example.tld</domain:host> <domain:host>ns2.example.tld</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 type="pw">2fooBAR</domain:authInfo> </domain:infData> </resData> <unspec/> <trID> <clTRID>ABC-12346</clTRID> <svTRID>54322-XYZ</svTRID> </trID> </response> </epp>

The example response show many of the typical fields in any info response.   The common fields are as follows:

For domains, the following may also be there:

For hosts, the following info response fields may be present:

For contacts, the following fields may be present:

* Both of the address types contain the name, org, addr, voice, fax, and email elements.  The addr element further contains the street, city, sp, pc, and cc sub-elements.  “sp”, “pc” and “cc” being state/province, postal code, and country code, respectively.

Object Updates

With all three types of objects in the registry, we can now move on to the update command.

Generally, the update command contains three elements:  items to add, items to remove and items to change.  The items in each of these elements depend on the type of object being updated.  For example, you may add or remove contacts from a domain, or change the fax number of a contact.  Please note that whatever data elements where mandatory on object creation are still mandatory on update.  For example, if a domain requires at least one tech contact and you wish to change that contact, you’ll have add a new tech contact and remove the old one.  EPP allows you to perform those two actions in a single domain update command.

Another note:  a registrar may only update objects for which it is the current sponsoring registrar.

Domain Update

The updatable values for domain objects are the registrant, the contact list, the nameserver list, the status list and the auth info.  The registrant value is changeable (i.e. it “cannot” be removed or added, since it is not a list).  In the update command, simply specify a new value and the server will replace the old one.  If the registrant value is optional in the registry with which you are communicating, you may specify an empty tag (i.e. “<domain:registrant/>” or “<domain:registrant></domain:registrant>”) and the server will “remove” the existing value.  With the RTKs available today from Sourceforge, leaving the registrant value null or NULL will have it omitted from the XML request to signify to the server that no change is requested to the registrant value.  Specifying an empty string (i.e. “”) will force the RTK to send an empty tag to the server.   The registrant must be a valid contact in the registry in order for the update to be successful.

Since both the contact and nameserver parameters are lists, values may be added or removed from them.  In the update command, simply specify a valid contact or nameserver identifier to add a new value to the lists.  To remove an existing contact or nameserver from the domain’s current associations, specify that contact or nameserver in the “remove” list.  When removing a contact, the proper contact type must be specified in the remove list.  Since a single contact can cast in multiple roles with the domain, the registry needs to know specifically which contact to remove.

The status values are also contained in a list and can be added or removed.   The registrar is only permitted to add or remove stati that start with “client” (eg. “clientHold”).  Depending on the version of EPP in use at the registry, the list of available stati might vary (in the Java and the C++ RTK’s that use the IDLs defined by a group of registry operators, the list of stati is available in the epp_DomainStatusType class or enum).  When adding new stati to a domain, the registrar is permitted to specify a short text message to accompany the status.  When removing stati, the descriptive text should not be included.   Also if a status is already applied to a domain, the status cannot be applied again.  If the registrar wishes to change the status descriptive text, then the status must be removed and then re-added to the domain.  This should be possible to perform in a single update command.

The auth info is another changeable value.  As it is required for domain objects, it cannot be set to a blank value, in fact EPP imposes minimum and maximum length values on the auth info.

Here is an example of a domain update command:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <epp xmlns="urn:iana:xml:ns:epp-1.0" xmlns:xsi="" xsi:schemaLocation="urn:iana:xml:ns:epp-1.0 epp-1.0.xsd"> <command> <update> <domain:update xmlns:domain="urn:iana:xml:ns:domain-1.0" xsi:schemaLocation="urn:iana:xml:ns:domain-1.0 domain-1.0.xsd"> <domain:name>example.tld</domain:name> <domain:add> <domain:ns>ns1.example2.tld</domain:ns> <domain:contact type="tech">mak21</domain:contact> <domain:status s="clientHold" lang="en"> Payment overdue. </domain:status> </domain:add> <domain:rem> <domain:ns>ns2.example.tld</domain:ns> <domain:contact type="tech">sh8013</domain:contact> <domain:status s="clientUpdateProhibited"/> </domain:rem> <domain:chg> <domain:registrant>sh8013</domain:registrant> <domain:authInfo type="pw">2BARfoo</domain:authInfo> </domain:chg> </domain:update> </update> <unspec/> <clTRID>ABC-12346</clTRID> </command> </epp>

Contact Update

The contact update action is not as equally balanced as the domain update.   The bulk of the updateable data is in the “change” portion.  The only values that can be added or removed are contact stati.  The format for the status values is the same as in the domain update command (i.e. only client-usable status values, plus an optional descriptive text).

The changeable data for a contact is the address.  Both of them actually, since there’s an ASCII version and an I15D version.

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <epp xmlns="urn:iana:xml:ns:epp-1.0" xmlns:xsi="" xsi:schemaLocation="urn:iana:xml:ns:epp-1.0 epp-1.0.xsd"> <command> <update> <contact:update xmlns:contact="urn:iana:xml:ns:contact-1.0" xsi:schemaLocation="urn:iana:xml:ns:contact-1.0 contact-1.0.xsd"> <contact:id>sh8013</contact:id> <contact:add> <contact:status s="clientDeleteProhibited"/> </contact:add> <contact:chg> <contact:ascii> <contact:org/> <contact:addr> <contact:street>124 Example Dr.</contact:street> <contact:street>Suite 200</contact:street> <contact:city>Dulles</contact:city> <contact:sp>VA</contact:sp> <contact:pc>20166-6503</contact:pc> <contact:cc>US</contact:cc> </contact:addr> </contact:ascii> <contact:voice>+1.7034444444</contact:voice> <contact:fax/> <contact:authInfo type="pw">2BARfoo</contact:authInfo> </contact:chg> </contact:update> </update> <unspec/> <clTRID>ABC-12346</clTRID> </command> </epp>

Host Update

This is the simplest of the update commands.  For a host, IP addresses and stati may be added or removed.  Also, the host’s name may be changed.  The status additions and removals are the same as with domains and contacts.  The IP addresses follow the same format as in the host create (i.e. the actual IP address and address type).

The host update command allows for the full host name to be changed.  For instance, you may rename "ns1.domain.tld" to  "ns2.domain.tld". This should usually present no problem, so long as the former does not already exist.  You may also rename the domain in which the host resides.  For example, changing “ns1.domain1.tld” to “ns1.domain2.tld”.  Of course, to do this, “domain2.tld” must exist in the registry.  And if “domain2.tld” is outside of the TLD bounds of the registry, the restriction of no IP addresses comes into play.

Here a sample host update command:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <epp xmlns="urn:iana:xml:ns:epp-1.0" xmlns:xsi="" xsi:schemaLocation="urn:iana:xml:ns:epp-1.0 epp-1.0.xsd"> <command> <update> <host:update xmlns:host="urn:iana:xml:ns:host-1.0" xsi:schemaLocation="urn:iana:xml:ns:host-1.0 host-1.0.xsd"> <host:name>ns1.example.tld</host:name> <host:add> <host:addr ip="v4"></host:addr> <host:status s="clientUpdateProhibited"/> </host:add> <host:rem> <host:addr ip="v6">1080:0:0:0:8:800:200C:417A</host:addr> </host:rem> <host:chg> <host:name>ns2.example.tld</host:name> </host:chg> </host:update> </update> <unspec/> <clTRID>ABC-12346</clTRID> </command> </epp>

Object Deletions

Just as you can create objects in a registry, you can delete them too.  Of course, you must be the current sponsoring registrar in order to successfully delete an object.  There also might be further restrictions on some objects.  For instance, objects associated to other objects cannot be deleted until the association is removed.  An example of this would be a contact being associated with a domain.  The contact cannot be deleted until its associate with the domain is removed (via the domain update command).  Note though that the domain can be delete without disassociated it from the contacts and hosts.  The delete (once the object truly disappears) automatically frees associated objects.

All delete commands follow the sample simple pattern.  All that is required is the object's identifier (domain name, host name or contact ID or ROID).  Here is a delete command for a host object:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <epp xmlns="urn:iana:xml:ns:epp-1.0" xmlns:xsi="" xsi:schemaLocation="urn:iana:xml:ns:epp-1.0 epp-1.0.xsd"> <command> <delete> <host:delete xmlns:host="urn:iana:xml:ns:host-1.0" xsi:schemaLocation="urn:iana:xml:ns:host-1.0 host-1.0.xsd"> <host:name>ns1.example.tld</host:name> </host:delete> </delete> <unspec/> <clTRID>ABC-12346</clTRID> </command> </epp>

Note that some registries may impose time restrictions on object deletions, especially in regard to domains.  It is common for a registry to allow a "hard" delete within 5 days of domain creation, and to provide a "soft" delete after the first 5 days.  A "hard" delete is when the domain is truly removed from the registry upon successful delete.  A "soft" delete adds the "pendingDelete" status to the domain.  A registry-defined period of time later (often 5 days) the domain will truly disappear.  This is to allow accidental deletes to be undone, though that usually requires a call to the registry operator support staff.  Check with the registry with which you are dealing to determine the policies applicable to you.

Beyond Basic Operations in EPP

Outside the basic check, info, create, update and delete, there's a few more operations available to some objects.

Domain Renewals

When a domain is created, a "period" is usually specified by the registrar (or defaulted by the registry if it's absent from the command).  The period, in years or in months, defines the lifetime of the domain object.   After that period passes, the domain expires.  Although, things may not be that simple.  We'll deal with registry policies in a moment.   First, let's take a look at extending the validity period of a domain.  

(Note that none of this section applies to Contact or Host objects.  Those objects never expire, although when and if a domain expires, the child hosts, if any, will likely be locked, which could affect the resolution of other domains they serve.)

Anytime before a domain expires, it may be renewed by the sponsoring registrar.  The expiry date of a domain can be found through the domain info command.  The original expiry date is also returned on domain creation.  In the domain renew command, three values can be provided:   the domain name (required), the current expiry date (year, month and day -- required) and the renewal period (optional).  The current expiry is required to provide idempotency to the renew command.  This means that the same renew command cannot be processed multiple times.  This protects the registrar against such things as "double clicks" from the registrant, incomplete renew requests because of a broken connection to the registry or, otherwise, bugs in registrar code.  To issue a subsequent renewal on the same domain, the new expiry date must be used (it is provided in the renew response).  The period allows the registrar to specify a value other than the registry's default renewal period (which is often a year).  According to EPP, the renewal period can be anywhere from 0 to 99 years or months.  Registries often narrow this down a little ('cause 0 years is just silly).  Typically, a registry limits the expiration date of a domain to be no more than 10 years in the future.

Now, what happens when a domain expires?  Well, this depends heavily on registry policy.  EPP does not define any action that the registry must take when an object expires.  Registries tend to treat domains similar to magazine subscriptions.  Registrant retention is important because it generates revenue.  So registries will try to encourage registrants (through their registrars) to renew their domains.  This is also good for registrars because it means revenue to them as well.  Typical actions you might see a registry take are auto-renewal of domains which have expired.   Normally the registrar will have a grace period during which the domain can be deleted with no charge.  Some registries might simply extend the life of the domain for a short period of time to give late registrants time to decide on renewal, and attempt to delete the domain if there is no action taken by the registrar.  The registrar should be aware that during these "grace" periods, the domains might go into a locked state where the name is no longer resolvable in DNS.  If there are hosts in that domain that are serving other domains, then those domains might become unresovable as well.   Between registry-auto-renewals and notifications to registrants, domain expiry and renewal can be a complex matter.  Be sure to contact your registry operator to make sure you know which policies are in place.

Those with experience with RRP and Verisign’s com/net/org registry will know that domain expiry and renewals can be tricky.  The registrar’s system should be proactive in dealing with domain expirations using, perhaps, advance notifications to the registrant.  Some registrants might just never respond, so the registrar should be able to delete the domain before there is a charge for the auto-renewal.

Object Transfers

In EPP, both domain and contact objects may transferred between registrars.   This changes the sponsorship of the object in the registry from the losing to the gaining registrar.  The key to object transfers is the authorization information for each object.  For those coming from RRP, the auth info is what prevents registrars from “stealing” domains (and now contacts) from other registrars.  Only the current sponsoring registrar, and, consequently, the registrant, have access to the auth info (via the “info” command).  The registrant gives this string to the registrar to which they wish to transfer.  This allows the requesting (or “gaining”) registrar to issue a transfer for an object and to query its current transfer status.  Once an object is successfully transferred, the gaining registrar should recommend the registrant change their auth info for the transferred object so that the losing registrar cannot reclaim the object without the registrant’s permission in a subsequent transfer.

The transfer command in EPP has several operations:  query, request, approve, reject and cancel.  The requesting registrar should perform a transfer query first to ensure that the auth info is valid.  Here is the transfer query command for a domain object:

<?xml version="1.0" standalone="no"?> <epp xmlns="urn:iana:xml:ns:epp" xmlns:xsi="" xsi:schemaLocation="urn:iana:xml:ns:epp epp.xsd"> <command> <transfer op="query"> <domain:transfer xmlns:domain="urn:iana:xml:ns:domain" xsi:schemaLocation="urn:iana:xml:ns:domain domain.xsd"> <domain:name>example.tld</domain:name> <domain:authInfo type="pw">2fooBAR</domain:authInfo> </domain:transfer> </transfer> <unspec/> <clTRID>ABC-12346</clTRID> </command> </epp>

The response would look something like this:

<?xml version="1.0" standalone="no"?> <epp xmlns="urn:iana:xml:ns:epp" xmlns:xsi="" xsi:schemaLocation="urn:iana:xml:ns:epp epp.xsd"> <response> <result code="1000"> <msg>Command completed successfully</msg> </result> <resData> <domain:trnData xmlns:domain="urn:iana:xml:ns:domain" xsi:schemaLocation="urn:iana:xml:ns:domain domain.xsd"> <domain:name>example.tld</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> <unspec/> <trID> <clTRID>ABC-12346</clTRID> <svTRID>54322-XYZ</svTRID> </trID> </response> </epp>

The response contains the information of the current or most recent transfer issued on the queried object.  If the object has never been transferred, then the EPP registry will return an error code.  If the trStatus is “pending” then a transfer is currently being executed on the object.  Other stati for transfers are: approved, cancelled, rejected, autoApproved, and autoCancelled.  Those all indicate that the last transfer operation is complete and another may be issued.  The “reID” and “reDate” are the client id of the requesting registrar, and the date of the request, respectively.  The “acID” is the ID of the “losing” registrar for that transfer request.  The “acDate” can have two meanings.  If the transfer is pending, then the acDate is the date by which the losing registrar can take action on the transfer (i.e. approve or reject it).  If the transfer is complete, then this is the date when the transfer was finalized (either by the losing registrar approving or rejecting it, the gaining registrar cancelling it or by the EPP registry taking automatic action).  The proposed expiry date from transferring domains is in “exDate”.  This member will not be present for contact transfers since contacts never expire.

Maybe this would be a good time to talk about how transfers work in EPP.   RRP users will find most of this familiar.

  1. A registrant goes to a new registrar with their domain.  Maybe the new registrar has a better package deal with better prices?
  2. The registrant provides the auth info to the registrar.
  3. The registrar issues a transfer request, with an optional renewal period.  If the auth info provided was invalid, then the transfer request will fail.  (A transfer “query” could have told the registrar this, but why perform in two requests to the registry what you can accomplish with a single request?)
  4. If the request was successful, the current sponsoring registrar receives notification that a domain of theirs is being transfered away.
  5. Depending on registry policy, the losing registrar might have a couple of days to proactively approve or reject the transfer.  The requesting registrar also has a chance to cancel the transfer request during this time.
  6. If the losing registrar takes no action, the registry will likely automatically approve or reject the transfer depending on their policies.  Most will usually auto-approve transfers.
  7. The gaining registrar should receive notification of the results of the transfer.  If the transfer is successful, the gaining registrar will be charged for the renewal period of the domain.  If none was specified in the request, the registry usually assigns a default (often 1 year).

So, here’s the transfer request for a domain:

<?xml version="1.0" standalone="no"?> <epp xmlns="urn:iana:xml:ns:epp" xmlns:xsi="" xsi:schemaLocation="urn:iana:xml:ns:epp epp.xsd"> <command> <transfer op="request"> <domain:transfer xmlns:domain="urn:iana:xml:ns:domain" xsi:schemaLocation="urn:iana:xml:ns:domain domain.xsd"> <domain:name>example.tld</domain:name> <domain:period unit="y">2</domain:period> <domain:authInfo type="pw">2fooBAR</domain:authInfo> </domain:transfer> </transfer> <unspec/> <clTRID>ABC-12346</clTRID> </command> </epp>

Notice that the requesting registrar is asking for a 2 year renewal.  The response to the transfer should be identical to the transfer query request.  In fact, responses to all types of transfer operations have the same format.

If the losing registrar wishes to take action on a transfer, the following command may be used:

<?xml version="1.0" standalone="no"?> <epp xmlns="urn:iana:xml:ns:epp" xmlns:xsi="" xsi:schemaLocation="urn:iana:xml:ns:epp epp.xsd"> <command> <transfer op="reject"> <domain:transfer xmlns:domain="urn:iana:xml:ns:domain" xsi:schemaLocation="urn:iana:xml:ns:domain domain.xsd"> <domain:name>example.tld</domain:name> <domain:authInfo type="pw">2fooBAR</domain:authInfo> </domain:transfer> </transfer> <unspec/> <clTRID>ABC-12346</clTRID> </command> </epp>

Only the domain name and auth info are required in the request from the losing registrar.

As mentioned in the steps above, the current sponsoring registrar will receive notification of a pending transfer.  This will likely be through the poll mechanism, which is described below.  The optional data that will appear in the poll response will be the results in a transfer query.

Registrar Session Management

As a registrar, it isn't simply enough to be able to manage objects.  As a registry client, you should be able to manage your sessions as well.  This includes such aspects as keeping a persistent connection alive during period of little or no activity and dealing with notifications from the registry.  Luckily, in EPP, those two can be accomplished with a single command:  Poll.


As stated ealier, polling accomplishes two goals:  keeping a session alive and retrieving notifications from the registry.  It's great for keeping a persistent connection alive because of its harmless nature.  Its default form is a query.  Registries that use EPP maintain a queue of messages and notifications for each registrar.  These messages will typically be regarding object transfers, but may also include such things as low balance notifications, pending domain expiry, auto-renewal notifications, and so on.  Unfortunately, with exception of a plain text message, EPP doesn't define the data that can be returned in a poll response.  This is up to registry policy and EPP extensions.

The way that poll works is such:  A registrar may poll its queue in the registry.  Poll comes in two operations:  Query and Acknowledge.   As a registry processes changes to objects, notifications may be added to the end the registrar's queue.  The registrar may use poll-query to retrieve the message sitting at the front of the queue.  If the queue is empty the response code and text will say that.  If there is a notification, there will be a message id, message text and optional data in the response.  The regsitrar must then issue a "poll/ack" to dequeue the message.  The notification's id must be supplied in the poll/ack.  The registrar repeats this process until the queue is empty.

Most registries will terminate a persistent connection if there is no activity on the connection for a given period of time (contact your regisry to find out that period).  For a single connection, the registrar should keep track of the last communication time and poll the registry when the elasped time is just under the registry timeout value.  If you poll too often, you might be needlessly taxing the registry's system and you might be wasting time when your

system processor could be doing something more productive.

RRP users can equate poll with the ‘describe’ command for keeping connections alive.  There is no equivalent of registry message queues in RRP.

EPP Response Codes

EPP organizes its error codes into groups.  There are two major headings:  success and failure.  The former has response codes in 1000s range.  The latter in the 2000s range.  Within these ranges the response codes are further divided.  The group is as follows:

x0xx -- Protocol syntax
x1xx -- Server policy and implementation rules
x2xx -- Security and authorization
x3xx -- Data management
x4xx -- Server and interal errors
x5xx -- Connection management

Every response in EPP contains a response and a corresponding text.  Along with that is a language indicator.  The default language is “en”.  Registries have the option of providing the message texts in the language which was indicated in the “creds” (for example, at login time).

1000 - Command completed successfully
Everything's a-okay!  The command was successful.  If a object was created, then an “info” should now be possible on that object.

1300 - Command completed successfully; no messages
Standard Poll response when there are no message waiting in the server for your registrar account.
1301 - <variable notification message from poll response>
Poll response where a meaning full message is provided.  Depending on the message, there might also be additional data included in the Poll reponse (eg. to identify the domain being transferred).

1500 - Command completed successfully; ending session
The standard reponse to a successful logout.

2000 - Unknow command
The registrar has sent the registry an unknown command (i.e. none of login, logout, hello, poll, check, info, create, update, delete, transfer, or renew).
2001 - Command syntax error
Generic error message when the server doesn’t understand what you’ve sent.  Maybe the XML is invalid.  Try passing it through a validator.  Perhaps you are including parameters that don’t belong to the command in question.
2002 - Command use error
The registrar is asking the registry to do something that is not valid in the current context, like a logout before a login.  Or a domain create (without creds) outside of a session in a connection-based transport (eg. TCP).
2003 - Required parameter missing
A domain create without the domain name.  Contact update without any “add”, “rem” and “chg” tags.  Something was missing in the request that the server requires to execute the command.
2004 - Parameter value range error
This error code can means a few things.  Most common causes are parameters that are too long (domain names, auth info, contact name, etc...).  It could also be used for numeric parameters that are either too large or too small for the range defined by the registry (eg. domain period).  Data should be verified as much as possible by the registrar before sending to the registry.  Return to the registrant and get him or her to correct the input data and resubmit.
2005 - Parameter value syntax error
The format of the parameter is not correct.  This usually does not include length checking, which should be covered by error code 2004.  A typical cause of this error code is in contact creates where the voice or fax phone number don’t match the E.164 format for international telephone numbers.  A (North American) example of this would be "+1.4165550101“.  The regular expression for this in the XML schemas is "(\+[0-9]{1,3}\.[0-9]{1,12})?".  The number between the “+” and “.” signs is the country’s dialing code.

2100 - Unimplemented protocol version
The registrar has attempted a login using a version of the protocol that is not supported by the registry.  The registrar is free to attempt further logins with different version numbers using the same connection.
2101 - Unimplemented command
This error will be returned if an action being attempted on an object is not implemented by either the protocol or the server.  For example, host renew.  Further attempts of this command will fail.
2102 - Unimplemented option
This error code would be returned if the registrar is attempting to issue a sessionless command (with creds)  when the server has not implemented that feature.  Essentially, 2102 will appear if the registrar is attempting a valid command with options that are not supported by the registry.
2103 - Unimplemented extension
An extension that the registar is attempting to use (maybe from another registry) is not supported by this registry.  Removing the extension from the XML request and retry the command.
2104 - Billing failure
This could means a few things.  The most command cause is that the registrar is out of funds in the registry.  Further retries of the command will fail until the registrar’s account balance is increased.  Some registries may implement a “low threshold” notification system so that registrars can be warned when their balance runs dangerously low.  If the registrar’s balance is not the problem, then the server may be experiencing internal problems.  The registry operator should be contacted in this case to report the problem.
2105 - Object is not eligible for renewal

2106 - Object is not eligible for transfer
A typical case for this error code and message would be trying to transfer an object shortly after it’s been created.  In the case of domain registries, some have defined a period of time after a domain has been created when transfers are not permitted.

2200 - Authentication error
In a session-based connection, this error code will be returned on a login if the client id or password are incorrect.  This can also be returned by any command in a sessionless situation where the command creds are invalid.
2201 - Authorization error
This response would normally occur when trying to perform an update, delete or renew an object that is not sponsored by the acting registrar.
2202 - Invalid authorization information
This response occurs if the auth info in the transfer command (query or request) is invalid.  Note that the auth info is not required for the approve, reject and cancel transfer operations.  The registrar should confirm the correctness of the auth info with the registrant before continuing.

2300 - Object pending transfer
If a domain is already in the midst of a transfer, this error will be returned by the registry.  Perhaps the registrant has forgotten that they have already requested a transfer (through you or via another registrar).  If your registrar is the losing registrar of the current pending transfer, maybe the registrant has changed his or her mind and wishes to return to you.  In that case, you can issue a transfer reject command on the object and the requesting registrar will be notified of the cancellation.
2301 - Object not pending transfer
This code will be returned if a transfer approve, reject or cancel is issue on an object that is not in a pending transfer state.  Perhaps the registrar’s records are out of sync with the registry.  Perform an info on the object and determine a new course of action.
2302 - Object exists
This error code will be returned if the registrar attempts to create an object that already exists.  The registrar should go back to the registrant to present other alternatives (maybe variations on the original domain name).  As the create command is usually the most resource-intensive in the registry, the registrar should avoid getting this message.  Using the check command before a create is *highly* recommended.  But in cases of race conditions (like at a scheduled release of a popular domain name), a create might still return this error code even after a check determined that the object was not known to the registry.
2303 - Object does not exist
Update, delete, renew and transfer commands will return this code if the object is not found in the registry.  Correct the request and try again.
2304 - Object status prohibits operation
Mostly self-explanatory.  Typical cases are trying to issue a transfer for an object that has been locked by the current sponsoring registrar.  Or an update to an object that is locked.  The current owning registrar would have to remove that status in order to allow the operation to be successful.  If the object is not your own, then perhaps there are compliance or legal issues that dictate that the object should locked until they are resolved.
2305 - Object association prohibits operation
This error could occur if the registrar tries to delete a host or contact which is currently associated to a domain.  The association must be broken before the delete is issued.
2306 - Parameter value policy error
This will typically happen when a request to the registry is within proper EPP bounds, but the registry has stricter validation.  For example, a domain create where the period exceeds the registry’s policy limits (most has a maximum of 10 years, where EPP allows for more).
2307 - Unimplemented object service
In this case, the registry might have defined a particular object, but does not permit all EPP actions to be performed upon it (like <contact:renew>).  Or perhaps, the registry has not defined the object at all.
2308 - Data management policy violation

2400 - Command failed
Something went wrong in the registry and none of the 2000, 2100, 2200 or 2300 error codes could handle the problem.  Verify the XML you are sending to the registry to see if it’s indeed valid.  If you are still stumped, it might be best to contact the registry operator.  Give them as much information as you can (XML logs are the best).

2500 - Command failed; server ending session
Similar to 2400, but this time the registry server thought that the command failure was fatal to your session and has decided to terminate it.  Same recommendations as with 2400.
2501 - Timeout; server ending session
There has been no activity on the connection for some time.  Some registry might send this message just before cutting the connection (although some may skip this message altogether).  Increase your polling frequency and reconnect.
2502 - Session limit exceeded; server closing connection
The registry has implemented a limit to the number of connections a registrar may have.  This may be the same for all registrars or may be adjustable depending on the registrar’s registration rate.  Either reduce the number of connections your are attempting or contact the registry operator to see if the limit may be move up for your registrar.  Note that some registries might simply refuse additional connections (base on source IP address) without sending this message.

There is an implementation of a Registrar Toolkit available from SourceForge that has two additional error code, which are not part of the protocol and which are not generated by the registry.  If you use this toolkit, you might encounter these error codes.

2600 - Communications failure
This error usually occurs as a connection is being attempted.  Perhaps the connection information is incorrect or the server is down, or unreachable.  Retrying the connection couldn’t hurt, but further investigation is recommended.
2601 - Unexpected server disconnect
The operating system has signalled to the client that the server has closed its end of the socket connection.  Retrying the connection is recommended, unless something unusual has occured (physical network connection broken, etc...).  If this occurs immediately after a successful connection, then perhaps the SSL/TLS certicate the registrar is using has expired or its signing certificate authority is not recognized by the server.  Another possibility is that the registrar’s system has reach its limit on connection to the registry.

EPP Versions

Because of the issues of contractual launch dates and schedules, some registries have opted to take a snapshot of the Extensible Provisioning Protocol in a point in time and implement that version.  At the time of this writing, Afilias’ .info registry is using a version of EPP which dates around April 2001.  As other registries launch synchronous registration systems other versions will be in place.

The latest specs can always be found at the IETF ( ).   They are currently in Internet Draft form and can be found at .

The version used by the .info registry can be found in the the EPP-RTK distribution from Sourceforge.  Download any distribution in the 0.3.X version range here .  The specs are contained in two directories under epp-rtk/java/doc/epp.    epp01 is the directory that contains the draft docs for the "01" release of the protocol.  epp02 is the directory that contains the XML schemas for the pre-release of the "02" spec.  Unfortunately, no drafts exist for these schemas.  The registrar should read the drafts on epp01 and then supplement that with the schemas from epp02.


If after reading this document, you still more information or if you have any questions, browse over to -- this will lead you to the SF site for the EPP-RTK project.  From there you can sign up for the epp-rtk-devel or epp-rtk-general mailing lists.  Ask your questions there or search through the archives to see if anyone else has already asked the same questions.  Feel free also to post questions on the discussion boards (though the mailing lists are better).

Document History

 Daniel Manley; Aug 23, 2001; Initial release; ver 0.1.0.
 Daniel Manley; Aug 30, 2001; Minor spelling corrections and misc rewording where clarity was lacking; ver 0.1.1
 Daniel Manley; Sept 10, 2001; EPP corrections and rewording so that the document better reflects the text of the protocol specs; ver 0.1.2
 Daniel Manley; Sept 28, 2001; added more descriptions to the EPP Response codes; ver 0.1.3

Author Credits

This document was orignally written by Daniel Manley (, in August of 2001, at the request of Liberty Registry Management Services, the outsourcer of the .info registry for Afilias.  I hope those reading this will feel a little more at ease with EPP.

I’d also like to thank Scott Hollenbeck, the author of EPP, for his input into this document... and for the use of his XML examples.