Skip to content
Pidgely Docs

API reference · Domains

Create a domain

POSThttps://api.pidgely.com/domains
View as Markdown

Adds a sending domain and returns the DNS records to publish: DKIM (TXT), the return-path MX and SPF TXT on a subdomain (bounces by default, change it with custom_return_path), and an optional DMARC TXT. Then call Verify a domain, or wait for the automatic checks.

A domain can be verified by only one account, and your plan sets how many domains you can add. Receiving and open/click tracking are not supported yet: capabilities.receiving: "enabled" is rejected and the tracking flags are always false.

Authorization: Bearer pdg_…. An API key with full_access. A sending_access key gets 401 restricted_api_key.

Body parameters

JSON object.

Name Type Required Description
name string Yes Display name.
region string No Informative; set by the platform.
custom_return_path string No Bounce subdomain label (default bounces).
tls string No opportunistic (default): TLS when the receiving server offers it. enforced: deliver only over TLS. One of opportunistic, enforced.
open_tracking boolean No Accepted, not supported yet (always false).
click_tracking boolean No Accepted, not supported yet.
capabilities object No —
capabilities.sending string No —
capabilities.receiving string No enabled is rejected (receiving not supported yet).

Request

Node.js
import { Pidgely } from 'pidgely';

const pidgely = new Pidgely(process.env.PIDGELY_API_KEY);

const { data, error } = await pidgely.domains.create({
  name: 'acme.com',
  customReturnPath: 'bounces',
  tls: 'opportunistic',
});
console.log(data ?? error);
Python
import os
import pidgely

pidgely.api_key = os.environ["PIDGELY_API_KEY"]

result = pidgely.Domains.create({
    "name": "acme.com",
    "custom_return_path": "bounces",
    "tls": "opportunistic",
})
print(result)
PHP
<?php

require __DIR__ . '/vendor/autoload.php';

$pidgely = Pidgely::client(getenv('PIDGELY_API_KEY'));

$result = $pidgely->domains->create([
    'name' => 'acme.com',
    'custom_return_path' => 'bounces',
    'tls' => 'opportunistic',
]);
var_dump($result);
Go
package main

import (
	"context"
	"fmt"
	"os"

	"github.com/pidgely/pidgely-go"
)

func main() {
	ctx := context.Background()
	client := pidgely.NewClient(os.Getenv("PIDGELY_API_KEY"))

	result, err := client.Domains.Create(ctx, &pidgely.CreateDomainRequest{
		Name:             "acme.com",
		CustomReturnPath: "bounces",
		Tls:              "opportunistic",
	})
	if err != nil {
		panic(err)
	}
	fmt.Println(result)
}
Ruby
require "pidgely"

Pidgely.api_key = ENV["PIDGELY_API_KEY"]

result = Pidgely::Domains.create({
  name: "acme.com",
  custom_return_path: "bounces",
  tls: "opportunistic"
})
puts result
cURL
curl -X POST 'https://api.pidgely.com/domains' \
  -H "Authorization: Bearer $PIDGELY_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "acme.com",
  "custom_return_path": "bounces",
  "tls": "opportunistic"
}'

Response

200 OK

JSON
{
  "object": "domain",
  "id": "0199d7f0-1c2b-7e4d-a5f6-0b9c8d7e6f51",
  "name": "acme.com",
  "status": "not_started",
  "created_at": "2026-10-12 16:44:41.000000+00",
  "region": "sa-east-1",
  "open_tracking": false,
  "click_tracking": false,
  "tls": "opportunistic",
  "capabilities": {
    "sending": "enabled",
    "receiving": "disabled"
  },
  "records": [
    {
      "record": "DKIM",
      "name": "pdg202610._domainkey",
      "type": "TXT",
      "ttl": "Auto",
      "status": "not_started",
      "value": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA…"
    },
    {
      "record": "SPF",
      "name": "bounces",
      "type": "MX",
      "ttl": "Auto",
      "status": "not_started",
      "value": "mta.pidgely.com",
      "priority": 10
    },
    {
      "record": "SPF",
      "name": "bounces",
      "type": "TXT",
      "ttl": "Auto",
      "status": "not_started",
      "value": "v=spf1 include:_spf.mta.pidgely.com ~all"
    },
    {
      "record": "DMARC",
      "name": "_dmarc",
      "type": "TXT",
      "ttl": "Auto",
      "status": "not_started",
      "value": "v=DMARC1; p=none;"
    }
  ]
}

Response fields

Name Type Required Description
object string No Object type.
id string No Unique id (UUID). UUID.
name string No Display name.
status string No Current status. One of not_started, pending, verified, failed.
created_at string No Timestamp in UTC (2026-10-12 16:44:41.000000+00).
region string No Informative; set by the platform.
open_tracking boolean No —
click_tracking boolean No —
tls string No opportunistic (default): TLS when the receiving server offers it. enforced: deliver only over TLS. One of opportunistic, enforced.
capabilities object No —
capabilities.sending string No —
capabilities.receiving string No —
records object[] No DNS records to publish, with their verification status.
records[].record string No One of DKIM, SPF, DMARC.
records[].name string No Relative to the domain.
records[].type string No One of TXT, MX.
records[].ttl string No —
records[].status string No Current status.
records[].value string No Record value.
records[].priority integer No MX priority.

Errors

Errors have the shape {"statusCode", "name", "message"}. See Errors for the full list.

Status Name When
401 missing_api_key, restricted_api_key No Authorization: Bearer header, or a sending_access key called an endpoint that needs full_access.
403 invalid_api_key, validation_error The API key is invalid or revoked, or the request is not allowed for this account (unverified domain, plan limit, paused account).
404 not_found The resource does not exist in this account (or the id is not a valid UUID).
422 validation_error A field is missing or invalid; message names it.
429 rate_limit_exceeded Too many requests per second. Wait for Retry-After seconds.
403 validation_error The domain already exists in this account, or the plan limit on domains is reached.