Domain registrant dossier
A paid .vn domain whose registrant details or dossier (ID card eKYC, an organisation's declaration) are not complete yet has an order but is not registered with VNNIC: status Pending. The four routes below let the customer's software see which domains are waiting, what is still missing, and update the registrant; once the dossier is complete Tino registers the domain automatically.
Updated: 2026-10-27.
A domain with an incomplete dossier is not reserved: someone else can still register it. Under Circular 48/2025/TT-BKHCN, "first come, first served" only applies to domains whose procedure is complete and paid. Remind customers to finish early.
Routes and scopes
| Route | Purpose | Scope |
|---|---|---|
| `GET /v1/domains/pending` | Domains not activated yet and what is left to do | domains:registrant |
| `GET /v1/domains/{id}/registrant` | Registrant and dossier status of one waiting domain | domains:registrant |
| `PUT /v1/domains/{id}/registrant` | Save the registrant (new details or another domain's registrant); Tino tries to register right away | domains:registrant |
| `GET /v1/registrants` | Registrants of the customer's running domains, to pick again | domains:registrant |
All four routes need domains:registrant (view and complete the registrant dossier of domains awaiting registration): this scope is only available to personal API tokens with an IP restriction; OAuth apps and the MCP server are never granted it. The routes return the customer's own full registrant data (ID number, date of birth, phone, address): never write these fields to logs.
eKYC and declarations are done in Tino's Client Area (tino.vn), not through the API.
Waiting domains
GET /v1/domains/pending, oldest first:
{
"domains": [
{
"id": 200001,
"name": "example.vn",
"status": "Pending",
"subject_type": "ind",
"ready": false,
"actions": [{ "code": "ekyc", "message": "Chủ thể cần eKYC CCCD trong tài khoản này" }],
"reason": "Chưa eKYC CCCD 001******001"
}
]
}| Field | Meaning |
|---|---|
subject_type | ind individual · org organisation · hkd household business |
ready | true: dossier complete, Tino is registering the domain (a few minutes) |
actions | what the customer still has to do (table below); empty with ready: false means the declaration was submitted and awaits Tino's review |
reason | why the latest registration attempt did not go through; may be null. ID numbers (runs of 9–13 digits) in the sentence are masked, keeping only the first 3 and last 3 digits |
No waiting domains: {"domains": []}. A registered domain leaves this list and becomes Active in GET /v1/domain.
message and reason are Vietnamese sentences meant for the customer.
What is left to do
actions[].code | Task |
|---|---|
fields | Missing or invalid fields listed in fields (e.g. ["nationalid", "city"]): fix them, then PUT |
owner_fields | Same, for the owner of a household business |
ekyc, owner_ekyc | The registrant (or owner) must complete eKYC with the declared ID card, in this same account |
ekyc_name, owner_ekyc_name | The declared name differs from the eKYC name: correct it to match the ID card, then PUT |
ekyc_other_account, owner_ekyc_other_account | The ID card was verified in another Tino account: use another registrant or contact Tino |
declaration | Organisation: submit the signed declaration (or digitally sign the organisation dossier) in the Client Area |
Reading the registrant
GET /v1/domains/{id}/registrant:
{
"domain": { "id": 200001, "name": "example.vn", "status": "Pending" },
"subject_type": "ind",
"registrant": {
"firstname": "Van A", "lastname": "Nguyen", "companyname": "", "taxid": "", "householdsid": "",
"nationalid": "001090000001", "birthday": "1990-01-01", "gender": "M", "email": "user@example.com",
"phonenumber": "0900000001", "country": "VN", "state": "Thành phố Hồ Chí Minh", "city": "Phường Bến Thành", "ward": "",
"address1": "123 Example Street", "address2": "", "postcode": "", "position": ""
},
"owner": null,
"dossier": { "ekyc": "required", "declaration": "not_needed" },
"actions": [{ "code": "ekyc", "message": "Chủ thể cần eKYC CCCD trong tài khoản này" }],
"reason": "Chưa eKYC CCCD 001******001",
"ready": false
}stateandcityare the names of the province / city and ward (post-merger list), not codes.owner: the household owner (name, ID number…) whensubject_typeishkd; VNNIC checks the owner's eKYC. Other types:null.dossier.ekyc:ok·required·name_mismatch·other_account·not_needed(organisations, non-.vnextensions).dossier.declaration(organisations):accepted·pending(submitted, awaiting review) ·cancelled(rejected) ·none·not_needed.dossier.signature:ok(organisation dossier digitally signed for the tax code) ·none.
Reusing an earlier registrant
GET /v1/registrants returns the registrants of the customer's running domains, newest first, one row per person / organisation:
{
"registrants": [
{ "from_domain_id": 200002, "domain": "example.com.vn", "subject_type": "ind", "registrant": { "…": "as above" }, "owner": null, "ready": true, "actions": [] }
]
}ready: true: the registrant completed eKYC (or digital signing) in this account, so a new domain can be registered right away. An organisation that only has a paper declaration on the old domain has ready: false and a declaration action: declarations belong to each domain and must be submitted again.
Saving the registrant
PUT /v1/domains/{id}/registrant, JSON body, one of two forms:
{ "from_domain_id": 200002 }{
"registrant": {
"firstname": "Van A", "lastname": "Nguyen", "nationalid": "001090000001", "phonenumber": "0900000001",
"state": "Thành phố Hồ Chí Minh", "city": "Phường Bến Thành", "address1": "123 Example Street",
"email": "user@example.com", "birthday": "1990-01-01", "gender": "M", "country": "VN"
},
"owner": null
}- Send every field of the registrant: a field left out counts as empty; unknown fields are ignored.
- Required for
.vn:firstname,lastname,nationalid,phonenumber,state,city,address1; organisations addcompanyname,taxid; household businesses addhouseholdsidandowner(firstname,lastname,nationalid). Other extensions:firstname,lastname,email,phonenumber,address1,city,country. - After saving, Tino tries to register right away and returns the new dossier (same shape as
GET); readactionsandreadyagain for the next step. Without another call, the system retries about every 5 minutes. - Only for waiting domains. To change the registrant of an
Activedomain: `PUT /v1/domain/{id}/contact`.
Errors
Errors look like {"error": ["<Vietnamese sentence>"]} and can be shown to the customer as is.
| HTTP | Sentence | When |
|---|---|---|
| 403 | insufficient_scope | the token lacks domains:registrant (an OAuth app's token, or a personal token without this scope) |
| 404 | Không tìm thấy tên miền chờ đăng ký | the domain is Active, cancelled, or not the customer's |
| 422 | Tên miền không tồn tại hoặc đã kích hoạt | PUT on a domain that is no longer waiting |
| 422 | Thiếu city (… fields) | a required field is missing |
| 422 | Trường state không hợp lệ | the value is not a string or is longer than 255 characters |
| 422 | Hộ kinh doanh cần thông tin chủ hộ (owner) | a household business without owner |
| 422 | Không dùng được chủ thể của tên miền #N | from_domain_id is not one of the customer's running domains |