curl --request POST \
--url https://api.reply.io/v3/email-accounts/procurement/domains/{domainId}/renew \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.reply.io/v3/email-accounts/procurement/domains/{domainId}/renew"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.reply.io/v3/email-accounts/procurement/domains/{domainId}/renew', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.reply.io/v3/email-accounts/procurement/domains/{domainId}/renew",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.reply.io/v3/email-accounts/procurement/domains/{domainId}/renew"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.reply.io/v3/email-accounts/procurement/domains/{domainId}/renew")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.reply.io/v3/email-accounts/procurement/domains/{domainId}/renew")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"jobId": "3f6c2a1e-8b4d-4c1f-9a7e-5d2b0c6e9f14"
}Renew a purchased domain
New. This endpoint shipped recently. If anything about it is unclear or could work better for you, tell us in the developer Slack.
channels:write scope (or a broader one that includes it).
Renews one domain your team bought for another year and charges the card on file. Preview the price first with POST /v3/email-accounts/procurement/domains//renew/estimate.
A domain can be renewed while its subscription is active and it expires in 1 to 45 days — renewStatus is renewable in GET /v3/email-accounts/procurement/domains. Only the team owner, or a member with billing permission, can renew.
Returns a jobId — poll GET /v3/background-jobs/ for the outcome. Nothing has been charged when the 202 arrives. The job stays Processing until the provider confirms the renewal, which can take up to three days. When it ends as Done, its jsonDataResult carries the new expireOn and renewalPriceCents, the price the charge was checked against.
When the job ends as Failed, its jsonDataResult carries an errorCode and a failureMessage. The codes in the first table mean nothing was charged, and you can retry at once:
errorCode | Meaning |
|---|---|
procurementDomain.featureDisabled | Domain renewal is not enabled for your team. |
procurementDomain.notFound | The domain no longer exists. |
procurementDomain.validation | The domain is a pre-warmed domain, which cannot be renewed. |
procurementDomain.renewalInProgress | Another renewal of this domain started in the meantime. Do not retry; check renewStatus. |
procurementDomain.notRenewable | Either the domain stopped being renewable (its subscription is not active, or it is outside the 45-to-1-day window), or the renewal cannot be charged for this workspace right now — review the billing settings in the app, then retry. The failureMessage says which. |
procurementDomain.renewalPriceUnavailable | The renewal price could not be confirmed: the provider may be temporarily unavailable, or may no longer offer a renewal for this domain. Retry later, or contact support if this persists. |
procurementDomain.temporarilyUnavailable | One of three cases, told apart by the failureMessage: a transient failure (retry); the renewal could not be reliably priced (retry, or contact support if this persists); or the discount the renewal was priced with is no longer valid (retry — the renewal is priced without it). |
procurementDomain.paymentDeclined | Either the payment could not be completed — check the payment method in billing settings, then retry — or payments are disabled for this workspace — contact support to enable them, then retry. |
procurementDomain.paymentActionRequired | The saved payment method needs interactive authentication, which this API cannot complete. Update the payment method or complete billing verification in the app, then retry. |
The codes in the second table mean the payment may have been taken. Do not renew again — a new request for the same domain is refused with 409 for 24 hours. Contact support with the jobId:
errorCode | Meaning |
|---|---|
procurementDomain.renewalFailed | The provider reported that the renewal failed, so the domain was not renewed. The charge needs review. |
procurementDomain.renewalNotConfirmed | One of three cases, told apart by the failureMessage: the payment was processed, but the renewal could not be confirmed with the provider; the payment may or may not have been charged; or the provider never reported a final status for the renewal. |
If the job ends as Expired, nothing reported progress for 26 hours and the job was closed: jsonDataResult is {"timedOut": true}, with no errorCode. The outcome is unknown — the payment may have been taken and the domain renewed. Do not renew again: check expireOn in GET /v3/email-accounts/procurement/domains, and contact support with the jobId.
curl --request POST \
--url https://api.reply.io/v3/email-accounts/procurement/domains/{domainId}/renew \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.reply.io/v3/email-accounts/procurement/domains/{domainId}/renew"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.reply.io/v3/email-accounts/procurement/domains/{domainId}/renew', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.reply.io/v3/email-accounts/procurement/domains/{domainId}/renew",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.reply.io/v3/email-accounts/procurement/domains/{domainId}/renew"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.reply.io/v3/email-accounts/procurement/domains/{domainId}/renew")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.reply.io/v3/email-accounts/procurement/domains/{domainId}/renew")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"jobId": "3f6c2a1e-8b4d-4c1f-9a7e-5d2b0c6e9f14"
}Authorizations
Authenticate every request with a Bearer token. Pass your Reply API key in the
Authorization header:
Authorization: Bearer <your-api-key>
Get your API key from the Reply dashboard: Settings → API Key.
Path Parameters
The domainId from GET /v3/email-accounts/procurement/domains
x >= 1Response
Renewal accepted; poll the returned job for the outcome
Poll GET /v3/background-jobs/{jobId} for the outcome