Renew a domain
POST /v1/domain-purchases/:id/renew — extend the registration. Charges wholesale + $1.
POST /v1/domain-purchases/:id/renew
Charges your saved Stripe card wholesale + $1 per year and extends the
domain's registration at the upstream registrar. Same charge-first ordering
as the initial buy: refunds automatically if the renewal fails at the
registrar.
Request
curl -X POST https://api.domainee.dev/v1/domain-purchases/f8a0c1b9-…/renew \
-H "Authorization: Bearer $DOMAINEE_API_KEY" \
-d '{ "years": 1 }'
Body parameters
| Field | Required | Notes |
|---|---|---|
years | ✅ | Integer 1–10. How many additional years to add to the registration. |
Response — 200 OK
The updated purchase row with the new expiresAt:
{
"purchase": {
"id": "f8a0c1b9-…",
"hostname": "janesbakery.com",
"expiresAt": "2028-05-17T15:42:11.000Z",
"status": "completed",
...
}
}
Errors
| Code | Status | When |
|---|---|---|
not_found | 404 | Purchase doesn't exist in this workspace. |
wrong_status | 409 | Purchase status isn't completed. Can't renew a failed/refunded purchase. |
billing_required | 402 | Stripe charge failed. Same reasons as the initial buy — declined card, expired, etc. |
renewal_failed | 502 | Card charged, registrar refused. We've already refunded the Stripe charge. |
Side effects
- Stripe charge for
wholesale × years + $1is captured on the workspace. - Domain's
expiresAtadvances at the registrar. - Webhook fired:
domain_purchase.renewedon success ordomain_purchase.renewal_failedon failure.
Manual vs. auto-renew
This endpoint is manual — Acme calls it when they want to charge for
another year. There's also an automatic path: set autoRenew: true on a
purchase (via PATCH /:id or
at create time), and the background worker will call this endpoint for
you 30 days before expiry.
Pick the model that matches your billing relationship with your end-user:
| Your model | Use |
|---|---|
| End-user pays you yearly via subscription | autoRenew: true — set it once, renewals happen automatically every year |
| End-user pays per-renewal manually | Keep autoRenew: false and call this endpoint when they pay you |
| End-user might churn — you want to gate renewal on their account status | Keep autoRenew: false. In your own cron, check who's active, then call this endpoint for the active ones |