# Set up DNS automatically

> Detect a domain's DNS provider and apply records automatically via Cloudflare, GoDaddy, or Namecheap.

MailBlastr can apply your domain's DNS records for you if your domain is managed by **Cloudflare**, **GoDaddy**, or **Namecheap**. The flow is: detect which provider the domain uses, then call the matching apply endpoint with your provider API credentials. MailBlastr upserts the SPF, DKIM, and DMARC records and immediately triggers a verification pass.

All three endpoints require a key with at least **read** access for detect, and **full** access for the apply endpoints.

## Detect provider

`GET /domains/:id/dns/detect`

Looks up the nameservers for the domain and identifies which DNS provider is in use. Returns the provider details and a `methods` array listing which one-click apply options are available for that provider.

**Node.js**

```js
import { MailBlastr } from 'mailblastr';

const mb = new MailBlastr('mb_xxxxxxxxx');

const { data, error } = await mb.domains.detectDns('d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e');
console.log({ data, error });
```

**Ruby**

```ruby
require "mailblastr"

Mailblastr.api_key = "mb_xxxxxxxxx"

Mailblastr::Domains.detect_dns("d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e")
```

**PHP**

```php
$mailblastr = Mailblastr::client('mb_xxxxxxxxx');

$mailblastr->domains->detectDns('d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e');
```

**Python**

```python
import mailblastr

mailblastr.api_key = "mb_xxxxxxxxx"

mailblastr.Domains.detect_dns("d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e")
```

**Go**

```go
package main

import (
    "fmt"
    "io"
    "net/http"
)

func main() {
    req, _ := http.NewRequest("GET", "https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/detect", nil)
    req.Header.Set("Authorization", "Bearer mb_xxxxxxxxx")
    res, _ := http.DefaultClient.Do(req)
    defer res.Body.Close()
    out, _ := io.ReadAll(res.Body)
    fmt.Println(string(out))
}
```

**Rust**

```rust
use reqwest::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let res = Client::new()
        .get("https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/detect")
        .header("Authorization", "Bearer mb_xxxxxxxxx")
        .send()
        .await?;
    println!("{}", res.text().await?);
    Ok(())
}
```

**Java**

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/detect"))
    .header("Authorization", "Bearer mb_xxxxxxxxx")
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
```

**.NET**

```csharp
using System.Net.Http;
using System.Text;

var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/detect");
request.Headers.Add("Authorization", "Bearer mb_xxxxxxxxx");
var response = await client.SendAsync(request);
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

**cURL**

```bash
curl -X GET 'https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/detect' \
  -H 'Authorization: Bearer mb_xxxxxxxxx'
```

**CLI**

```bash
mailblastr domains dns detect d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e
```

### Response

```json
{
  "provider": {
    "id": "cloudflare",
    "label": "Cloudflare",
    "domainConnect": false,
    "api": true
  },
  "nameservers": ["ns1.cloudflare.com", "ns2.cloudflare.com"],
  "methods": [
    {
      "type": "cloudflare",
      "label": "Connect Cloudflare",
      "needs": "api_token"
    },
    {
      "type": "open_panel",
      "label": "Open Cloudflare DNS settings",
      "url": "https://dash.cloudflare.com/?to=/:account/:zone/dns"
    }
  ]
}
```

The `provider.id` is one of `cloudflare`, `godaddy`, `namecheap`, `ionos`, `google`, `route53`, or `other`. Each object in `methods` describes one available path: `cloudflare` and `godaddy` entries include a `needs` field indicating the credential the apply endpoint requires; `open_panel` entries include a `url` deep-link to the provider's DNS settings page.

Errors: `not_found` if the domain does not exist or is not yours. See [Errors](https://www.mailblastr.com/docs/api/errors).

## Apply via Cloudflare

`POST /domains/:id/dns/cloudflare`

Upserts the domain's SPF, DKIM, and DMARC records directly into your Cloudflare zone using a scoped API token, then immediately triggers a verification pass and returns the resulting domain status. The token must have **Zone → DNS → Edit** permission on the domain's zone.

**Node.js**

```js
import { MailBlastr } from 'mailblastr';

const mb = new MailBlastr('mb_xxxxxxxxx');

const { data, error } = await mb.domains.applyCloudflareDns('d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e', { "token": "cf_token_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" });
console.log({ data, error });
```

**Ruby**

```ruby
require "mailblastr"

Mailblastr.api_key = "mb_xxxxxxxxx"

Mailblastr::Domains.apply_cloudflare_dns("d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e", {
  "token": "cf_token_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
})
```

**PHP**

```php
$mailblastr = Mailblastr::client('mb_xxxxxxxxx');

$mailblastr->domains->applyCloudflareDns('d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e', [
  'token' => "cf_token_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
]);
```

**Python**

```python
import mailblastr

mailblastr.api_key = "mb_xxxxxxxxx"

mailblastr.Domains.apply_cloudflare_dns("d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e", {
  "token": "cf_token_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
})
```

**Go**

```go
package main

import (
    "fmt"
    "io"
    "net/http"
    "strings"
)

func main() {
    req, _ := http.NewRequest("POST", "https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/cloudflare", strings.NewReader(`{ "token": "cf_token_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }`))
    req.Header.Set("Authorization", "Bearer mb_xxxxxxxxx")
    req.Header.Set("Content-Type", "application/json")
    res, _ := http.DefaultClient.Do(req)
    defer res.Body.Close()
    out, _ := io.ReadAll(res.Body)
    fmt.Println(string(out))
}
```

**Rust**

```rust
use reqwest::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let res = Client::new()
        .post("https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/cloudflare")
        .header("Authorization", "Bearer mb_xxxxxxxxx")
        .header("Content-Type", "application/json")
        .body(r#"{ "token": "cf_token_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }"#)
        .send()
        .await?;
    println!("{}", res.text().await?);
    Ok(())
}
```

**Java**

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/cloudflare"))
    .header("Authorization", "Bearer mb_xxxxxxxxx")
    .header("Content-Type", "application/json")
    .method("POST", HttpRequest.BodyPublishers.ofString("""
{ "token": "cf_token_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }
"""))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
```

**.NET**

```csharp
using System.Net.Http;
using System.Text;

var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/cloudflare");
request.Headers.Add("Authorization", "Bearer mb_xxxxxxxxx");
request.Content = new StringContent(@"{ ""token"": ""cf_token_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"" }", Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

**cURL**

```bash
curl -X POST 'https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/cloudflare' \
  -H 'Authorization: Bearer mb_xxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{ "token": "cf_token_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }'
```

**CLI**

```bash
mailblastr domains dns cloudflare d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e \
  --token 'cf_token_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
```

### Response

```json
{
  "applied": 3,
  "updated": 0,
  "failed": [],
  "zoneId": "023e105f4ecef8ad9ca31a8372d0c353",
  "status": "verified"
}
```

`applied` is the count of records created, `updated` is the count of records overwritten (already existed with a different value), and `failed` is a list of any records that could not be written — each entry has `host` and `error`. `status` is the domain verification status after the immediate re-check (`verified`, `pending`, or `failed`).

> **Warning:** The token must be a **scoped API token** (not your Global API Key). Create one under My Profile → API Tokens → Create Token → "Edit zone DNS" template, and scope it to the domain's zone.

Errors: `not_found` if the domain does not exist or is not yours, `validation_error` if the token is missing, rejected by Cloudflare (bad scope or wrong account), or the domain's zone is not found in this Cloudflare account. See [Errors](https://www.mailblastr.com/docs/api/errors).

## Apply via GoDaddy

`POST /domains/:id/dns/godaddy`

Upserts the domain's SPF, DKIM, and DMARC records into GoDaddy via the GoDaddy Domains API, then immediately triggers a verification pass and returns the resulting domain status. Use a **Production** API key — OTE keys will not work against live domains.

**Node.js**

```js
import { MailBlastr } from 'mailblastr';

const mb = new MailBlastr('mb_xxxxxxxxx');

const { data, error } = await mb.domains.applyGoDaddyDns('d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e', { "key": "gd_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx", "secret": "gd_secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" });
console.log({ data, error });
```

**Ruby**

```ruby
require "mailblastr"

Mailblastr.api_key = "mb_xxxxxxxxx"

Mailblastr::Domains.apply_godaddy_dns("d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e", {
  "key": "gd_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "secret": "gd_secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
})
```

**PHP**

```php
$mailblastr = Mailblastr::client('mb_xxxxxxxxx');

$mailblastr->domains->applyGoDaddyDns('d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e', [
  'key' => "gd_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  'secret' => "gd_secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
]);
```

**Python**

```python
import mailblastr

mailblastr.api_key = "mb_xxxxxxxxx"

mailblastr.Domains.apply_godaddy_dns("d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e", {
  "key": "gd_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "secret": "gd_secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
})
```

**Go**

```go
package main

import (
    "fmt"
    "io"
    "net/http"
    "strings"
)

func main() {
    req, _ := http.NewRequest("POST", "https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/godaddy", strings.NewReader(`{ "key": "gd_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx", "secret": "gd_secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" }`))
    req.Header.Set("Authorization", "Bearer mb_xxxxxxxxx")
    req.Header.Set("Content-Type", "application/json")
    res, _ := http.DefaultClient.Do(req)
    defer res.Body.Close()
    out, _ := io.ReadAll(res.Body)
    fmt.Println(string(out))
}
```

**Rust**

```rust
use reqwest::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let res = Client::new()
        .post("https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/godaddy")
        .header("Authorization", "Bearer mb_xxxxxxxxx")
        .header("Content-Type", "application/json")
        .body(r#"{ "key": "gd_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx", "secret": "gd_secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" }"#)
        .send()
        .await?;
    println!("{}", res.text().await?);
    Ok(())
}
```

**Java**

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/godaddy"))
    .header("Authorization", "Bearer mb_xxxxxxxxx")
    .header("Content-Type", "application/json")
    .method("POST", HttpRequest.BodyPublishers.ofString("""
{ "key": "gd_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx", "secret": "gd_secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" }
"""))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
```

**.NET**

```csharp
using System.Net.Http;
using System.Text;

var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/godaddy");
request.Headers.Add("Authorization", "Bearer mb_xxxxxxxxx");
request.Content = new StringContent(@"{ ""key"": ""gd_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"", ""secret"": ""gd_secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"" }", Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

**cURL**

```bash
curl -X POST 'https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/godaddy' \
  -H 'Authorization: Bearer mb_xxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{ "key": "gd_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx", "secret": "gd_secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" }'
```

**CLI**

```bash
mailblastr domains dns godaddy d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e \
  --key 'gd_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
  --secret 'gd_secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxx'
```

### Response

```json
{
  "applied": 3,
  "failed": [],
  "status": "verified"
}
```

`applied` is the count of records written and `failed` is a list of any records that could not be written — each entry has `host` and `error`. `status` is the domain verification status after the immediate re-check (`verified`, `pending`, or `failed`). Unlike the Cloudflare response, GoDaddy does not return an `updated` count because its API replaces records by type/name rather than patching individual record IDs.

> **Warning:** Use a **Production** key from the GoDaddy Developer Portal. OTE (test environment) keys will return 404 for live domains.

Errors: `not_found` if the domain does not exist or is not yours, `validation_error` if key or secret is missing, rejected by GoDaddy (bad credentials or wrong environment), or the domain is not in this GoDaddy account. See [Errors](https://www.mailblastr.com/docs/api/errors).

## Apply via Namecheap

`POST /domains/:id/dns/namecheap`

Applies the domain's SPF, DKIM, and DMARC records via the Namecheap API, then immediately triggers a verification pass. Namecheap's host API is a full replace, so MailBlastr first reads your existing host records and re-sends them unchanged alongside the new ones — your current DNS is preserved.

**Node.js**

```js
import { MailBlastr } from 'mailblastr';

const mb = new MailBlastr('mb_xxxxxxxxx');

const { data, error } = await mb.domains.applyNamecheapDns('d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e', { "apiUser": "your_namecheap_username", "apiKey": "nc_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" });
console.log({ data, error });
```

**Ruby**

```ruby
require "mailblastr"

Mailblastr.api_key = "mb_xxxxxxxxx"

Mailblastr::Domains.apply_namecheap_dns("d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e", {
  "apiUser": "your_namecheap_username",
  "apiKey": "nc_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
})
```

**PHP**

```php
$mailblastr = Mailblastr::client('mb_xxxxxxxxx');

$mailblastr->domains->applyNamecheapDns('d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e', [
  'apiUser' => "your_namecheap_username",
  'apiKey' => "nc_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
]);
```

**Python**

```python
import mailblastr

mailblastr.api_key = "mb_xxxxxxxxx"

mailblastr.Domains.apply_namecheap_dns("d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e", {
  "apiUser": "your_namecheap_username",
  "apiKey": "nc_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
})
```

**Go**

```go
package main

import (
    "fmt"
    "io"
    "net/http"
    "strings"
)

func main() {
    req, _ := http.NewRequest("POST", "https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/namecheap", strings.NewReader(`{ "apiUser": "your_namecheap_username", "apiKey": "nc_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" }`))
    req.Header.Set("Authorization", "Bearer mb_xxxxxxxxx")
    req.Header.Set("Content-Type", "application/json")
    res, _ := http.DefaultClient.Do(req)
    defer res.Body.Close()
    out, _ := io.ReadAll(res.Body)
    fmt.Println(string(out))
}
```

**Rust**

```rust
use reqwest::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let res = Client::new()
        .post("https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/namecheap")
        .header("Authorization", "Bearer mb_xxxxxxxxx")
        .header("Content-Type", "application/json")
        .body(r#"{ "apiUser": "your_namecheap_username", "apiKey": "nc_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" }"#)
        .send()
        .await?;
    println!("{}", res.text().await?);
    Ok(())
}
```

**Java**

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/namecheap"))
    .header("Authorization", "Bearer mb_xxxxxxxxx")
    .header("Content-Type", "application/json")
    .method("POST", HttpRequest.BodyPublishers.ofString("""
{ "apiUser": "your_namecheap_username", "apiKey": "nc_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" }
"""))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
```

**.NET**

```csharp
using System.Net.Http;
using System.Text;

var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/namecheap");
request.Headers.Add("Authorization", "Bearer mb_xxxxxxxxx");
request.Content = new StringContent(@"{ ""apiUser"": ""your_namecheap_username"", ""apiKey"": ""nc_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"" }", Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

**cURL**

```bash
curl -X POST 'https://api.mailblastr.com/domains/d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e/dns/namecheap' \
  -H 'Authorization: Bearer mb_xxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{ "apiUser": "your_namecheap_username", "apiKey": "nc_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" }'
```

**CLI**

```bash
mailblastr domains dns namecheap d91a7c4e-1f2b-4a8c-9e3d-7b5f0a2c1d6e \
  --api-user 'your_namecheap_username' \
  --key 'nc_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx'
```

### Response

```json
{
  "applied": 3,
  "preserved": 2,
  "failed": [],
  "status": "verified"
}
```

`applied` is the number of new records added, `preserved` is the number of your existing host records kept in place, and `failed` lists any that could not be written. `status` is the verification status after the immediate re-check.

> **Warning:** Namecheap validates the **calling server's IP** against your account allowlist. If you haven't whitelisted MailBlastr's IP, the request returns a `validation_error` telling you to add it under Profile → Tools → API Access. Enable API access there first and create the API key.
