E-mail and URL Forwarding

7 views Markdown

The seven endpoints that send a domain's mail and its visitors somewhere else.

Overview

These seven endpoints decide where what arrives at a domain goes. They are two separate jobs: an e-mail forward moves the mail, a URL forward moves the visitor.

An e-mail forward opens no mailbox; the mail is passed on as it is. A URL forward points the domain at another address without hosting a site on it.

Reference

Listing the E-mail Forwards

get/api/v1/admin/services/{id}/domain/email-forwards
Services/GetDomainEmailForwards admin

Returns the records saying where mail to the domain is passed on.

Response fields data[] — 4
identitystringThe record id. When the module gives none it is derived from the prefix and the target, so changing the target changes the id.
prefixstringThe local part of the source address.
sourcestringThe full source address. Worked out from the prefix and the domain.
targetstringWhere the mail is passed on to.
Errors 6
not_found404No such service.
not_domain422The service is not a domain.
no_module422No registrar module is attached.
not_supported422The module does not support this operation.
module_failed500The registry could not complete the operation.
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/services/520/domain/email-forwards' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch('https://panel.example.com/api/v1/admin/services/520/domain/email-forwards', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/services/520/domain/email-forwards');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// 'source' is a worked-out field; it appears on reads ONLY, never on writes.
$forwards = Api::Services()->GetDomainEmailForwards(['id' => 520])['data'];
Response
{
  "data": [
    {
      "identity": "3001",
      "prefix": "info",
      "source": "[email protected]",
      "target": "[email protected]"
    }
  ]
}

Adding an E-mail Forward

post/api/v1/admin/services/{id}/domain/email-forwards
Services/AddDomainEmailForward admin 201

Passes mail arriving at one of the domain's addresses on to another.

Body 2
prefixstringrequiredThe local part of the source address. The domain is appended for you.
targetstringrequiredWhere to pass the mail on to. Its format is validated.
Response fields data — 2
prefixstringThe source prefix of the forward added.
targetstringThe target it now points to.
Errors 7
not_found404No such service.
not_domain422The service is not a domain.
no_module422No registrar module is attached.
not_supported422The module does not support this operation.
email_fwd_fields_required422One of the required fields was empty.
invalid_email422The target is not a valid e-mail address.
insufficient_scope403The key lacks the required scope.
Request
curl -X POST 'https://panel.example.com/api/v1/admin/services/520/domain/email-forwards' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"prefix":"info","target":"[email protected]"}'
const res = await fetch('https://panel.example.com/api/v1/admin/services/520/domain/email-forwards', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ prefix: 'info', target: '[email protected]' }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/services/520/domain/email-forwards');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'prefix' => 'info',
        'target' => '[email protected]',
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The prefix is the local part ONLY: sending a full address produces '[email protected]@example.com'.
Api::Services()->AddDomainEmailForward([
    'id'     => 520,
    'prefix' => 'info',
    'target' => '[email protected]',
]);

Updating an E-mail Forward

put/api/v1/admin/services/{id}/domain/email-forwards
Services/UpdateDomainEmailForward admin only the target changes

Changes where a forward points. The source prefix cannot be changed.

Body 4
prefixstringrequiredThe source prefix of the record to change.
target_newstringrequiredThe new target address.
targetstringThe current target. It tells apart several records on the same prefix.
identitystringThe record id from the list.
Response fields data — 2
prefixstringThe source prefix of the record changed.
targetstringThe target it now points to. This is the value you sent as target_new.
Errors 7
not_found404No such service.
not_domain422The service is not a domain.
no_module422No registrar module is attached.
not_supported422The module does not support this operation.
email_fwd_fields_required422One of the required fields was empty.
invalid_email422The target is not a valid e-mail address.
insufficient_scope403The key lacks the required scope.
Request
curl -X PUT 'https://panel.example.com/api/v1/admin/services/520/domain/email-forwards' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"prefix":"info","target":"[email protected]","target_new":"[email protected]"}'
const res = await fetch('https://panel.example.com/api/v1/admin/services/520/domain/email-forwards', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    prefix: 'info',
    target: '[email protected]',
    target_new: '[email protected]',
  }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/services/520/domain/email-forwards');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'prefix'     => 'info',
        'target'     => '[email protected]',
        'target_new' => '[email protected]',
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// There is no endpoint for changing the prefix: delete the old one and add a new one.
Api::Services()->DeleteDomainEmailForward(['id' => 520, 'prefix' => 'info']);

Api::Services()->AddDomainEmailForward([
    'id'     => 520,
    'prefix' => 'contact',
    'target' => '[email protected]',
]);

Deleting an E-mail Forward

delete/api/v1/admin/services/{id}/domain/email-forwards
Services/DeleteDomainEmailForward admin

Removes an e-mail forward.

Body 3
prefixstringrequiredThe source prefix of the record to delete.
targetstringThe target. It narrows the match.
identitystringThe record id from the list.
Response fields data — 2
deletedboolWhether the delete succeeded.
prefixstringPrefix of the deleted record.
Errors 6
not_found404No such service.
not_domain422The service is not a domain.
no_module422No registrar module is attached.
not_supported422The module does not support this operation.
email_fwd_fields_required422One of the required fields was empty.
insufficient_scope403The key lacks the required scope.
Request
curl -X DELETE 'https://panel.example.com/api/v1/admin/services/520/domain/email-forwards' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"prefix":"info"}'
const res = await fetch('https://panel.example.com/api/v1/admin/services/520/domain/email-forwards', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ prefix: 'info' }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/services/520/domain/email-forwards');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['prefix' => 'info']),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// With several targets on one prefix, sending the prefix alone can delete ALL of them.
Api::Services()->DeleteDomainEmailForward([
    'id'     => 520,
    'prefix' => 'info',
    'target' => '[email protected]',
]);

Reading the URL Forward

get/api/v1/admin/services/{id}/domain/forwarding
Services/GetDomainForwarding admin

Returns whether the domain redirects to another address.

Response fields data — 4
activeboolWhether the forward is running.
methodintThe redirect type. Permanent or temporary; it defaults to permanent.
protocolstringWhich protocol the target is reached over.
domainstringThe address being redirected to.
Errors 6
not_found404No such service.
not_domain422The service is not a domain.
no_module422No registrar module is attached.
not_supported422The module does not support this operation.
module_failed500The registry could not complete the operation.
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/services/520/domain/forwarding' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch('https://panel.example.com/api/v1/admin/services/520/domain/forwarding', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/services/520/domain/forwarding');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$response = Api::Services()->GetDomainForwarding(['id' => 520]);

Setting the URL Forward

put/api/v1/admin/services/{id}/domain/forwarding
Services/SetDomainForwarding admin takes the site away

Sends visitors arriving at the domain to another address.

Body 3
domainstringrequiredThe address to redirect to.
protocolstringWhich protocol to reach the target over. It defaults to the unencrypted one.
methodintThe redirect type. It defaults to permanent, and a permanent redirect is cached by browsers.
Response fields data — 4
activeboolWhether the forward is running.
methodintThe redirect type. Permanent or temporary; it defaults to permanent.
protocolstringWhich protocol the target is reached over.
domainstringThe address being redirected to.
Errors 6
not_found404No such service.
not_domain422The service is not a domain.
no_module422No registrar module is attached.
not_supported422The module does not support this operation.
domain_fwd_url_required422The target address was empty.
insufficient_scope403The key lacks the required scope.
Request
curl -X PUT 'https://panel.example.com/api/v1/admin/services/520/domain/forwarding' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"domain":"example.net","protocol":"https","method":301}'
const res = await fetch('https://panel.example.com/api/v1/admin/services/520/domain/forwarding', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    domain: 'example.net',
    protocol: 'https',
    method: 301,
  }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/services/520/domain/forwarding');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'domain'   => 'example.net',
        'protocol' => 'https',
        'method'   => 301,
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// A permanent redirect is cached by browsers, so pick 302 while you are still trying things out.
Api::Services()->SetDomainForwarding([
    'id'       => 520,
    'domain'   => 'example.net',
    'protocol' => 'https',
    'method'   => 302,
]);

Removing the URL Forward

delete/api/v1/admin/services/{id}/domain/forwarding
Services/CancelDomainForwarding admin

Removes the redirect and leaves the domain to its own nameservers.

Response fields data — 1
cancelledboolWhether the redirect was removed.
Errors 6
not_found404No such service.
not_domain422The service is not a domain.
no_module422No registrar module is attached.
not_supported422The module does not support this operation.
module_failed500The registry could not complete the operation.
insufficient_scope403The key lacks the required scope.
Request
curl -X DELETE 'https://panel.example.com/api/v1/admin/services/520/domain/forwarding' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch('https://panel.example.com/api/v1/admin/services/520/domain/forwarding', {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/services/520/domain/forwarding');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Removing the redirect leaves the domain to its nameservers; with no DNS record the site will not open.
Api::Services()->CancelDomainForwarding(['id' => 520]);

$records = Api::Services()->GetDnsRecords(['id' => 520])['data'];

Pitfalls

The prefix is the local part only

Do not send the source address with the domain in it: the endpoint appends the domain to the prefix itself. Send a full address and you get a source with the domain twice, which never matches. The full address you see on a read is a worked-out field and is not used on writes.

Sending only the prefix can delete them all

Only the prefix is required on the delete. With several targets on one prefix, a request sent without a target or an id can remove all of them, because the module does the matching. Send the target too when you mean one record.

The prefix cannot be updated

The update only changes the target. Changing the source means deleting the record and adding a new one, and mail arriving in between is passed nowhere.

A permanent redirect sticks in the browser

The default redirect type is permanent and browsers cache it. Point a permanent redirect at the wrong target and fix it later, and users who visited before keep going to the old target for a while. Use the temporary type while trying things out.

Removing the forward does not bring a site back

With the forward gone the domain falls back to its own nameservers. If there is no record there the domain resolves nowhere, and because a forward was being used no DNS record may ever have been written. Look at the records before removing it.

Was this helpful?

Thanks for your feedback!

Still Need Help?

Our support team is here around the clock for anything you can't find above.