---
title: "Set up a domain you already own"
method: POST
path: "/v1/domains/setup"
tags: ["Domains"]
---

# Set up a domain you already own

`POST /v1/domains/setup`

## Request

- Base URL: `https://api.winnr.app`
- URL: `https://api.winnr.app/v1/domains/setup`
- Auth: HTTP bearer

Queue an already-registered domain for setup: configures DNS and sets
up email infrastructure (async). This endpoint does NOT register the
domain at a registrar and never charges for registration. To buy and
register a new domain, use `POST /v1/domains/purchase`. Requests with
`register: true` are rejected with a 400 error.

## Request body

- SetupDomainRequest
  - `domain` string, required: Domain name to set up. Must already be registered (you own it at an external registrar, or bought it via /v1/domains/purchase).
  - `setup_dns` boolean: Create the DNS zone and mail records (SPF, DKIM, DMARC, MX).
  - `setup_email` boolean: Create the domain on the mail infrastructure.
  - `users` object[]: Email users to create on the domain.
    - `name` string, required
    - `username` string, required
  - `redirect_url` string, nullable: Optional URL the domain root should redirect to.
  - `tags` string[]: Optional tags applied to the domain.

## Response `202`

Domain setup queued

- JobResponse
  - `data` Job: An async job tracking a long-running operation (domain setup/deletion, warming enable/disable, etc.). **Lifecycle:** `status` starts as `pending`, transitions to `in_progress` once the worker picks up the message, and ends as `completed` or `failed`. On `failed`, the `error` object describes what went wrong. **Progress map:** `progress` is a map of step name to step status (`pending` → `in_progress` → `completed`/`failed`/`skipped`). Step names depend on job type: - `domain_setup`: any subset of `registration`, `mailcow`, `dns_zone`, `dns_records` (only the steps requested by the original setup call are present) - `domain_delete`: `dns`, `mailcow`, `firebase` - `email_user_delete`, `warming_enable`, `warming_disable`: counter-shaped progress with `total`, `completed`, `failed` integer fields
    - `job_id` string: Unique job identifier.
    - `type` 'domain_setup' | 'domain_delete' | 'email_user_delete' | 'warming_enable' | 'warming_disable'
    - `status` 'pending' | 'in_progress' | 'completed' | 'failed'
    - `progress` object: Per-step progress for named-step jobs (domain_setup/domain_delete) or counter-shaped progress (`{total, completed, failed}`) for batch jobs.
    - `result` object, nullable: Operation result (shape varies by job type). `null` until job completes.
    - `error` object, nullable: Error details when `status=failed`.
      - `message` string
    - `created_at` string, date-time
    - `updated_at` string, date-time
    - `completed_at` string, date-time, nullable
  - `meta` Meta
    - `request_id` string
    - `timestamp` string, date-time

## Other responses

- `400`: Validation error
- `401`: Authentication required or token invalid

---

[API](https://skmtc.dev/winnr/apis/winnr-api.md) · [All operations](https://skmtc.dev/winnr/apis/winnr-api/llms.txt) · [OpenAPI document](https://skmtc.dev/winnr/apis/winnr-api/revisions/a4f960beb1eb?raw)
