← Back to docs

Warming API

Warming API

Manage IP and domain warming for your sending domains. Warming gradually increases your sending volume over several phases, building sender reputation with mailbox providers and ensuring high deliverability.

Warming Phases

Postscale uses a four-phase warming schedule with automatically enforced rate limits:

PhaseDurationDaily LimitDescription
phase_1Week 1-250 - 1,500Initial low-volume sending to establish reputation
phase_2Week 3-42,000 - 10,000Moderate volume with expanded ISP distribution
phase_3Week 5-615,000 - 60,000High volume with reputation monitoring
phase_4Week 7-8100,000 - 200,000Near-production volume before full graduation
warmedOngoingUnlimitedFully warmed with no warming restrictions

Advancement between phases is automatic when delivery metrics meet thresholds (delivery rate, bounce rate, complaint rate) and the minimum days in the current phase have elapsed.

Do not skip warming for new domains

Skipping the warming process for a new domain or IP can severely damage your sender reputation. Mailbox providers like Gmail, Microsoft, and Yahoo throttle or reject mail from unknown senders that suddenly transmit high volumes. Always complete the full warming schedule before sending at production volume.


Get Warming Status

GET /v1/domains/:id/warming

Retrieve the current warming status, rate limits, sending usage, and delivery metrics for a domain.

Example Request

curl -X GET https://api.postscale.io/v1/domains/d290f1ee-6c54-4b01-90e6-d701748f0851/warming \
  -H "Authorization: Bearer ps_live_your_api_key"

Response

{
  "domain_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
  "domain": "example.com",
  "phase": "phase_2",
  "warming_started_at": "2026-01-10T08:00:00Z",
  "phase_started_at": "2026-01-24T00:00:00Z",
  "days_in_current_phase": 5,
  "current_limits": {
    "daily_limit": 5000,
    "hourly_limit": 500,
    "per_minute_limit": 20
  },
  "today_sent": 1200,
  "this_hour_sent": 85,
  "remaining_today": 3800,
  "remaining_this_hour": 415,
  "metrics": {
    "period_days": 7,
    "total_sent": 8500,
    "total_delivered": 8415,
    "total_bounced": 85,
    "total_hard_bounce": 12,
    "total_complaints": 2,
    "total_opened": 3200,
    "total_clicked": 640,
    "delivery_rate": 0.99,
    "bounce_rate": 0.01,
    "hard_bounce_rate": 0.0014,
    "complaint_rate": 0.0002,
    "open_rate": 0.38,
    "click_rate": 0.076
  },
  "eligible_for_advancement": false,
  "advancement_blockers": [
    "minimum 7 days in phase required (currently 5)"
  ],
  "next_phase": "phase_3",
  "next_phase_limits": {
    "daily_limit": 15000,
    "hourly_limit": 1500,
    "per_minute_limit": 50
  }
}

Get Warming History

GET /v1/domains/:id/warming/history

Retrieve the phase transition history for a domain, including the reason and metrics snapshot for each transition.

Query Parameters

ParameterTypeDescription
limitintegerNumber of results to return (default: 50, max: 100)

Example Request

curl -X GET "https://api.postscale.io/v1/domains/d290f1ee-6c54-4b01-90e6-d701748f0851/warming/history?limit=10" \
  -H "Authorization: Bearer ps_live_your_api_key"

Response

{
  "domain_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
  "history": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "domain_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
      "from_phase": "phase_1",
      "to_phase": "phase_2",
      "reason": "metrics_passed",
      "metrics_snapshot": {
        "bounce_rate": 0.008,
        "complaint_rate": 0.0001,
        "delivery_rate": 0.992,
        "daily_volume": 1500,
        "days_in_phase": 14
      },
      "triggered_by": "system",
      "created_at": "2026-01-24T00:00:00Z"
    },
    {
      "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "domain_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
      "from_phase": "not_started",
      "to_phase": "phase_1",
      "reason": "warming_started",
      "triggered_by": "api",
      "created_at": "2026-01-10T08:00:00Z"
    }
  ]
}

Start Warming

POST /v1/domains/:id/warming/start

Start the warming process for a domain. The domain must have SPF or DKIM verified unless the force flag is set.

Request Body

FieldTypeRequiredDescription
forcebooleanNoSkip DNS verification checks (default: false)

Example Request

curl -X POST https://api.postscale.io/v1/domains/d290f1ee-6c54-4b01-90e6-d701748f0851/warming/start \
  -H "Authorization: Bearer ps_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "force": false
  }'

Response

{
  "message": "warming started",
  "phase": "phase_1"
}

Error: Prerequisites Not Met

If SPF and DKIM are not verified and force is false:

{
  "error": "prerequisites_not_met",
  "message": "Domain must have SPF or DKIM verified before starting warming",
  "spf_verified": false,
  "dkim_verified": false
}

Error: Already Warming

If the domain is already in an active warming phase:

{
  "error": "already_warming",
  "message": "Domain is already in warming phase",
  "current_phase": "phase_2"
}

Pause Warming

POST /v1/domains/:id/warming/pause

Pause the warming process for a domain. The domain must be in an active warming phase. While paused, no emails can be sent through the warming pipeline.

Request Body

FieldTypeRequiredDescription
reasonstringNoReason for pausing (default: "manual pause")

Example Request

curl -X POST https://api.postscale.io/v1/domains/d290f1ee-6c54-4b01-90e6-d701748f0851/warming/pause \
  -H "Authorization: Bearer ps_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "Investigating high bounce rate from Yahoo"
  }'

Response

{
  "message": "warming paused",
  "previous_phase": "phase_2",
  "reason": "Investigating high bounce rate from Yahoo"
}

Error: Not Warming

If the domain is not in an active warming phase:

{
  "error": "not_warming",
  "message": "Domain is not currently in an active warming phase",
  "current_phase": "not_started"
}

Resume Warming

POST /v1/domains/:id/warming/resume

Resume warming from a paused state. The domain returns to the phase it was in before it was paused.

Example Request

curl -X POST https://api.postscale.io/v1/domains/d290f1ee-6c54-4b01-90e6-d701748f0851/warming/resume \
  -H "Authorization: Bearer ps_live_your_api_key"

Response

{
  "message": "warming resumed",
  "phase": "phase_2"
}

Error: Not Paused

If the domain is not in a paused state:

{
  "error": "not_paused",
  "message": "Domain is not in paused state",
  "current_phase": "phase_2"
}

Warming Phase Values

PhaseDescription
not_startedWarming has not been initiated
phase_1Initial low-volume phase (week 1-2)
phase_2Moderate volume phase (week 3-4)
phase_3High volume phase (week 5-6)
phase_4Near-production volume phase (week 7-8)
warmedFully warmed, no warming restrictions
pausedWarming paused manually or due to metric thresholds
suspendedWarming suspended for policy violation