---
title: "Atomically ensure a site exists"
method: POST
path: "/api/sites/ensure"
tags: ["Sites"]
---

# Atomically ensure a site exists

`POST /api/sites/ensure`

## Request

- Base URL: `https://slimlytics.com`
- URL: `https://slimlytics.com/api/sites/ensure`
- Auth: HTTP bearer

Idempotent agent operation backed by a transaction and global canonical-domain uniqueness.

## Request body

- SiteInput
  - `name` string, required
  - `domain` string, required
  - `timezone` string
  - `allowedOrigins` string[]
  - `retentionDays` integer

## Response `200`

Existing site reused

- EnsureSiteResponse
  - `created` boolean, required
  - `site` Site, required
    - `id` string, uuid, required
    - `name` string, required
    - `domain` string, required
    - `timezone` string, required
    - `allowedOrigins` string[], required
    - `retentionDays` integer, required
    - `writeKey` string, uuid, required: Collection-only key; not an account credential
    - `serverWriteKey` string, uuid, required: Rotatable collection-only secret for trusted server request batches
    - `proxyKey` string, uuid, required: Server-side secret sent by the site's first-party proxy as X-Slimlytics-Proxy-Key with X-Slimlytics-Client-IP so locations and visitor IDs use the real visitor IP. Keep it out of public repositories; rotate with POST /api/sites/{siteId}/rotate-proxy-key if exposed
    - `antiAdblockServer` 'caddy' | 'nginx' | 'apache', required
    - `antiAdblockJsPath` string, required
    - `antiAdblockBeaconPath` string, required
    - `iconMode` 'initials' | 'favicon', required: Dashboard avatar: initials on a colored tile, or the website's favicon
    - `iconBackground` string, nullable, required: Tile gradient start; null uses an automatic per-domain hue
    - `iconBackgroundEnd` string, nullable, required: Tile gradient end; null keeps the background solid
    - `iconForeground` string, nullable, required: Initials color; null uses white
    - `iconUpdatedAt` string, date-time, nullable, required: When the stored favicon last changed; add it to the GET /api/sites/{siteId}/icon URL to bust caches
    - `createdAt` string, date-time, required

## Other responses

- `201`: New site created
- `400`: Invalid request
- `401`: Authentication required or invalid/expired credential
- `403`: Credential lacks permission
- `415`: Request Content-Type is not application/json
- `422`: JSON body could not be deserialized
- `500`: Internal service error

---

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