feat(domains): add forge activation methods

LU
17h ago
+384-5

Summary

Adds Forge activation to Domains, matching the folded API surface (the standalone forge verify and update endpoints no longer exist). Ports the Node implementation (resend/resend-node#1193, spec in resend/resend-openapi#144) into this SDK's idioms. Part of DEV-2472.

  • resend.Domains.Forge.enable({ "id": ..., "return_path": ... }) → POST /domains/{id}/forge. return_path is optional; when omitted, the API picks a label that is free in the domain's DNS. Returns the full domain response and is idempotent on the API side. Ships with its _async variant, like the rest of the SDK.
  • resend.Domains.verify(domain_id, params={ "scope": ["forge"] }) → POST /domains/{id}/verify. params is a new optional argument (Domains.VerifyParams, scope: List[Literal["forge"]]); scoped, only the Forge record is re-checked, so the records that are already verified are not re-proven. Without params the request is byte-identical to before. Same on verify_async.
  • resend.Domains.update({ "id": ..., "forge_return_path": ... }) → PATCH /domains/{id}. forge_return_path is a new UpdateParams key: moves the Forge return path while the Forge record is still verifying, does not start verification, and once the record verifies the API refuses with 422 return_path_unavailable. Composes with the other update fields.

Domain response types are unchanged: Forge state is read from the Forge CNAME record in the records array.

Validation

flake8 clean, mypy clean on the touched files, pytest: 875 tests passing. Tests assert the wire shapes: enable's empty body, verify's {"scope": ["forge"]} body (and {} without params), and update's forge_return_path, sync and async. examples/domain_forge.py now walks the folded flow: enable, move the path with Domains.update, verify scoped to forge.

Notes for reviewers

  • VerifyParams is a nested TypedDict on Domains with scope: NotRequired[List[VerifyDomainScope]], where VerifyDomainScope = Literal["forge"] lives next to TlsOptions.
  • The underlying class is DomainForge exposed as Domains.Forge (now enable-only), matching how DomainClaims is exposed as Domains.Claims.
  • Forge enable still strips id from the request body (it only addresses the path), following the ApiKeys.update precedent.

Summary by cubic

Adds a Forge subresource to Domains and folds Forge verification and return-path moves into the classic domain endpoints, per DEV-2472.

  • Domains.Forge.enable posts to /domains/{id}/forge with an optional return_path; id is stripped from the request body.
  • Domains.verify now accepts an optional scope: ["forge"] to re-check only the Forge record, and Domains.update accepts forge_return_path to move the return path without starting verification.
  • Bumps the SDK version to 2.54.0 and adds sync and async unit tests plus an examples/domain_forge.py example.

Validation

  • Unit tests cover URL, HTTP verb, body mapping, the empty-body enable, and the no-content error path for the new methods, sync and async.

The Forge enable endpoint is live in production; the scoped verify and forge_return_path land with the API reshape, which deploys before this ships. Ships with the next resend-python release.