Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 100 additions & 29 deletions rust/domains-client/openapi/domains.oas3.json

Large diffs are not rendered by default.

151 changes: 102 additions & 49 deletions rust/domains-client/openapi/swagger_domains.v3.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
openapi: 3.0.3
info:
title: Domain Lifecycle Management API
version: 3.0.0
version: 3.1.0
x-visibility: public
description: 'The GoDaddy Domain Lifecycle Management API provides comprehensive capabilities

Expand Down Expand Up @@ -670,12 +670,8 @@ paths:
quoteToken: 7f3a2b1c-9d8e-4012-a5b6-c1d2e3f4a5b6
consent:
agreementTypes:
- DNRA
- API_DPA
agreedAt: '2026-06-12T10:02:00Z'
agreedBy:
type: DIRECT
principal: shopper_123
ip: 203.0.113.7
security:
- oauth2:
- domains.domain:create
Expand All @@ -695,6 +691,31 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Registration'
examples:
accepted:
summary: Registration accepted with server-derived consent
value:
registrationId: 3a8f1c2d-7e6b-4f9a-b1c0-d2e3f4a5b6c7
domain: example.com
period: 1
price:
currencyCode: USD
value: 1199
consent:
agreementTypes:
- API_DPA
agreedAt: '2026-06-12T10:02:00Z'
agreedBy:
type: DIRECT
principal: 550e8400-e29b-41d4-a716-446655440000
ip: 203.0.113.7
status: CONFIRMED
operationId: 9f1c2e7a-4b3d-4e8f-a1c2-3d4e5f6a7b8c
createdAt: '2026-06-12T10:02:05Z'
updatedAt: '2026-06-12T10:02:05Z'
links:
- rel: self
href: /v3/domains/registrations/3a8f1c2d-7e6b-4f9a-b1c0-d2e3f4a5b6c7
'400':
$ref: '#/components/responses/400'
'401':
Expand Down Expand Up @@ -1415,8 +1436,8 @@ components:
$ref: '#/components/schemas/error'
'409':
description: 'Conflict — the request cannot be completed in the current state. Used for quote lifecycle errors (quote_expired,
quote_mismatch, quote_consumed, consent_principal_mismatch), domain state conflicts such as domain_already_exists,
and immutable DNS records (dns_record_not_mutable) such as GoDaddy-managed SOA and NS records.
quote_mismatch, quote_consumed), domain state conflicts such as domain_already_exists, and immutable DNS records (dns_record_not_mutable)
such as GoDaddy-managed SOA and NS records.

'
headers:
Expand Down Expand Up @@ -1474,7 +1495,7 @@ components:
description: 'The type of legal agreement. Identifies which agreement text the customer must accept.

'
example: DNRA
example: API_DPA
allOf:
- $ref: '#/components/schemas/AgreementType'
title:
Expand Down Expand Up @@ -1594,16 +1615,14 @@ components:
Consent:
title: Consent
description: 'Customer consent record for a domain operation, capturing which legal agreements were accepted, when,
and by whom. This object is self-reported by the caller and treated as supplementary attestation. The server verifies
agreedBy.principal against the authenticated identity (auth token + X-Shopper-Id resolution) and rejects with consent_principal_mismatch
on disagreement. The persisted consent record is the union of this claimed block and the verified auth context.
and by whom. On execute, the caller supplies agreementTypes and agreedAt. The server derives agreedBy from the authenticated
request context (OAuth identity, X-Shopper-Id, client IP, and transmission channel).

'
type: object
required:
- agreementTypes
- agreedAt
- agreedBy
properties:
agreementTypes:
type: array
Expand All @@ -1615,7 +1634,7 @@ components:

'
example:
- DNRA
- API_DPA
agreedAt:
description: 'The timestamp at which the principal expressed consent. Should reflect when the customer clicked accept
or confirmed the operation, not when the API call was made.
Expand All @@ -1624,16 +1643,16 @@ components:
allOf:
- $ref: '#/components/schemas/date-time'
agreedBy:
$ref: '#/components/schemas/ConsentActor'
description: 'Who gave consent and how it was transmitted. Server-derived from the execute request''s auth context.

'
readOnly: true
allOf:
- $ref: '#/components/schemas/ConsentActor'
ConsentActor:
title: Consent Actor
description: 'Identifies who gave consent and who transmitted it. One uniform schema for all actor types. Self-reported
by the caller and treated as supplementary attestation; the server verifies principal against the resolved auth identity
(OAuth token + X-Shopper-Id) and rejects with consent_principal_mismatch on disagreement. The persisted consent record
is the union of this block and the verified auth context.

principal identifies the account holder whose consent is being recorded. actor identifies the automated or intermediary
party that transmitted the consent when different from the principal. For DIRECT, actor is omitted.
description: 'Identifies who gave consent and how it was transmitted. One uniform schema for all actor types. Populated
by the server from the execute request''s authenticated context — not supplied by the caller.

'
type: object
Expand All @@ -1643,30 +1662,30 @@ components:
- principal
properties:
type:
description: 'Who transmitted consent relative to the principal.
description: 'How consent was transmitted relative to the principal. Server-assigned from the request''s auth and
channel context.

'
example: DIRECT
allOf:
- $ref: '#/components/schemas/ConsentActorType'
principal:
type: string
description: 'The shopper or account ID whose consent is being recorded. Must match the shopper resolved from the
OAuth token and X-Shopper-Id header; mismatch returns consent_principal_mismatch.
description: 'The resolved customer identifier whose consent is recorded, derived from the auth context on the execute
request.

'
example: shopper_123
example: 550e8400-e29b-41d4-a716-446655440000
actor:
type: string
description: 'The automated agent or system that transmitted the consent. Omitted for DIRECT. For AGENT, identifies
the specific agent instance. For RESELLER, may identify the reseller when distinct from the OAuth token subject.
description: 'The party that transmitted the consent when distinct from the principal. Omitted for DIRECT.

'
example: agent:claude/atlas-1
ip:
type: string
description: 'The IP address of the principal at the time consent was expressed, if known. Optional — an absent
IP with a verified principal is preferred over a fabricated one.
description: 'Client IP address captured from the execute request at the time consent was recorded. Omitted when
unavailable.

'
example: 203.0.113.7
Expand Down Expand Up @@ -2097,13 +2116,28 @@ components:

'
example: example.com
orderId:
type: string
description: 'The orderId of the order that created this registration. Present only when the registration is completed.
Not present for failed or pending registrations.

'
readOnly: true
period:
type: integer
minimum: 1
maximum: 10
default: 1
description: Registration period in years. Must match the period in the quote.
example: 1
price:
description: 'The locked registration price for the quoted period. Held for the duration of the quoteToken''s TTL.
Represents the total amount that will be charged on execute.

'
readOnly: true
allOf:
- $ref: '#/components/schemas/simple-money'
profileId:
description: 'ID of a saved registration profile to use for contacts and preference defaults. Omit to fall back
to the account-default profile for the domain''s TLD, then to account identity.
Expand All @@ -2129,8 +2163,8 @@ components:
allOf:
- $ref: '#/components/schemas/uuid'
consent:
description: 'The customer''s consent record for the legal agreements returned in the quote. Must reference the
same agreementTypes as the quote.
description: 'The customer''s consent for the legal agreements returned in the quote. On execute, supply agreementTypes
and agreedAt; agreedBy is server-derived and returned on the persisted record.

'
allOf:
Expand Down Expand Up @@ -2803,20 +2837,32 @@ components:
AgreementType:
title: Agreement Type
description: 'The type of legal agreement that must be accepted prior to executing a domain operation. Additional agreement
types may be returned for specific TLDs or product combinations. DNRA — Domain Name Registration Agreement. DNTA —
Domain Name Transfer Agreement. DNPA — Domain Name Privacy Agreement. HTTPS_NOTICE — HTTPS notice acknowledgment for
eligible TLDs. AURA — AU Domain Agreement for .au TLD registrations and transfers. CIRA — Canadian Internet Registration
Authority Agreement for .ca TLD registrations and transfers.
types may be returned for specific TLDs or product combinations. API_DPA - API Domain Purchase Agreement. DNTA — Domain
Name Transfer Agreement. DNPA — Domain Name Privacy Agreement. HTTPS_NOTICE — HTTPS notice acknowledgment for eligible
TLDs. AURA — AU Domain Agreement for .au TLD registrations and transfers. CIRA — Canadian Internet Registration Authority
Agreement for .ca TLD registrations and transfers.
Comment thread
jpage-godaddy marked this conversation as resolved.

'
type: string
enum:
- API_DPA
- AURA
- CIRA
- DNPA
- DNTA
- HTTPS_NOTICE
ConsentActorType:
title: Consent Actor Type
description: 'Who transmitted consent on behalf of the principal. DIRECT — the principal acted directly; actor is omitted.
AGENT — an AI or automation acted on behalf of the principal. RESELLER — a reseller acted on behalf of a shopper.
description: 'How consent was transmitted relative to the principal. DIRECT — the principal transmitted consent directly;
actor is omitted. AGENT — consent was transmitted by an AI or automation on the principal''s behalf. RESELLER — consent
was transmitted by a reseller on the principal''s behalf.

'
type: string
enum:
- AGENT
- DIRECT
- RESELLER
DomainOperationStatus:
title: Domain Operation Status
description: 'The execution state of an asynchronous domain operation. CONFIRMED — operation has been accepted and is
Expand All @@ -2826,19 +2872,24 @@ components:

'
type: string
enum:
- COMPLETED
- CONFIRMED
- EXECUTING
- FAILED
DomainStatus:
title: Domain Status
description: 'The lifecycle status of a registered domain. Reflects the domain''s current operational state within the registry
and GoDaddy''s management layer. ACTIVE — domain is registered and is active. CANCELLED — domain has been cancelled
by the user or system, and is not reclaimable. DELETED_REDEEMABLE — domain is in ICANN redemption grace period; recovery
fees apply. EXPIRED — registration period has ended; domain is pending deletion or redemption. FAILED - domain registration
or transfer error. HELD_REGISTRAR - domain is held at the registrar and cannot be transferred or modified - this is usually
the result of a dispute. LOCKED_REGISTRAR — domain is locked at the registrar - this is usually the result of spam,
abuse, etc. OWNERSHIP_CHANGED - domain has been moved to another account. PARKED - domain has been parked. PENDING_REGISTRATION
- domain is pending setup at the registry. PENDING_TRANSFER — an outbound transfer to another registrar is in progress.
REPOSSESSED - domain has been confiscated - this is usually the result of a chargeback, fraud, abuse, etc. SUSPENDED
— domain has been administratively suspended by the registry or registrar. TRANSFERRED - domain has been transferred
to another registrar.
description: 'The lifecycle status of a registered domain. Reflects the domain''s current operational state within the
registry and GoDaddy''s management layer. ACTIVE — domain is registered and is active. CANCELLED — domain has been
cancelled by the user or system, and is not be reclaimable. DELETED_REDEEMABLE — domain is in ICANN redemption grace
period; recovery fees apply. EXPIRED — registration period has ended; domain is pending deletion or redemption. FAILED
Comment thread
jpage-godaddy marked this conversation as resolved.
- domain registration or transfer error. HELD_REGISTRAR - domain is held at the registrar and cannot be transferred
or modified - this is usually the result of a dispute. LOCKED_REGISTRAR — domain is locked at the registrar - this
is usually the result of a spam, abuse, etc. OWNERSHIP_CHANGED - domain has been moved to another account. PARKED
- domain has been parked. PENDING_REGISTRATION - domain is pending setup at the registry. PENDING_TRANSFER — an outbound
transfer to another registrar is in progress. REPOSSESSED - domain has been confiscated - this is usually the result
of a chargeback, fraud, abuse, etc. SUSPENDED — domain has been administratively suspended by the registry or registrar.
TRANSFERRED - domain has been transferred to another registrar.

'
type: string
Expand All @@ -2864,6 +2915,8 @@ components:

'
type: string
enum:
- REGISTER
DNSRecordType:
title: DNS Record Type
description: 'The type of a DNS resource record. Values correspond to IANA-assigned DNS record type mnemonics. A — IPv4
Expand Down
37 changes: 25 additions & 12 deletions rust/domains-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ mod tests {
// v3 money is ISO-4217 minor units: USD 23.98 (2yr) -> 2398.
"price": { "currencyCode": "USD", "value": 2398 },
"requiredAgreements": [
{ "agreementType": "REGISTRATION", "title": "Registration Agreement",
{ "agreementType": "API_DPA", "title": "Registration Agreement",
"url": "https://x/agr" }
]
}));
Expand Down Expand Up @@ -277,8 +277,8 @@ mod tests {
);
let agreements = quote.required_agreements.expect("agreements");
assert_eq!(
agreements[0].agreement_type.as_ref().map(|a| a.as_str()),
Some("REGISTRATION")
agreements[0].agreement_type.as_ref().map(|a| a.to_string()),
Some("API_DPA".to_string())
);
}

Expand All @@ -297,7 +297,7 @@ mod tests {
"consent": {
"agreedAt": "2026-06-30T00:00:00Z",
"agreedBy": { "type": "DIRECT", "principal": "shopper-42", "ip": "127.0.0.1" },
"agreementTypes": ["REGISTRATION"]
"agreementTypes": ["API_DPA"]
}
}));
// The register response does NOT echo `quoteToken` (the token is
Expand All @@ -309,11 +309,11 @@ mod tests {
"consent": {
"agreedAt": "2026-06-30T00:00:00Z",
"agreedBy": { "type": "DIRECT", "principal": "shopper-42" },
"agreementTypes": ["REGISTRATION"]
"agreementTypes": ["API_DPA"]
},
"registrationId": "reg-1",
"operationId": "op-1",
"status": "PENDING"
"status": "EXECUTING"
}));
})
.await;
Expand All @@ -324,20 +324,25 @@ mod tests {
.body(types::Registration {
consent: types::Consent {
agreed_at: types::DateTime("2026-06-30T00:00:00Z".to_string()),
agreed_by: types::ConsentActor {
// Sending a client-side ConsentActor is still valid on the
// wire (the field is optional, not rejected) even though the
// server derives its own `agreedBy` from the auth context.
agreed_by: Some(types::ConsentActor {
actor: None,
ip: Some("127.0.0.1".to_string()),
principal: "shopper-42".to_string(),
type_: types::ConsentActorType("DIRECT".to_string()),
},
agreement_types: vec![types::AgreementType("REGISTRATION".to_string())],
type_: types::ConsentActorType::Direct,
}),
agreement_types: vec![types::AgreementType::ApiDpa],
},
created_at: None,
domain: "example.com".to_string(),
expires_at: None,
links: vec![],
operation_id: None,
order_id: None,
period: std::num::NonZeroU64::new(1).expect("nonzero"),
price: None,
profile: None,
profile_id: None,
quote_token: Some(types::Uuid("tok-abc".to_string())),
Expand Down Expand Up @@ -378,7 +383,10 @@ mod tests {
.into_inner();

mock.assert_async().await;
assert_eq!(op.status.as_ref().map(|s| s.as_str()), Some("COMPLETED"));
assert_eq!(
op.status.as_ref().map(|s| s.to_string()),
Some("COMPLETED".to_string())
);
}

// --- v3: domain get + nameservers + dns create --------------------------
Expand Down Expand Up @@ -463,8 +471,13 @@ mod tests {
.path("/v3/domains/domain-names/example.com/nameservers")
.header("Idempotency-Key", "idem-9")
.json_body(json!(["ns1.example.net", "ns2.example.net"]));
// `DomainOperationType` is spec'd as `enum: [REGISTER]` only, even
// though this endpoint's response is a `DomainOperation` too and a
// real nameserver-update operation would carry a different `type`
// (e.g. "UPDATE_NAMESERVERS") — a gap in the vendored spec, not this
// client. "REGISTER" is the only value that currently deserializes.
then.status(202)
.json_body(json!({ "operationId": "op-2", "type": "UPDATE_NAMESERVERS" }));
.json_body(json!({ "operationId": "op-2", "type": "REGISTER" }));
})
.await;

Expand Down
Loading