---
title: "Create a site template"
method: POST
path: "/v1/site-templates"
tags: ["Site templates"]
---

# Create a site template

`POST /v1/site-templates`

## Request

- Base URL: `https://api.feelingsurf.fr`
- URL: `https://api.feelingsurf.fr/v1/site-templates`
- Auth: HTTP bearer

A template is a reusable bundle of site settings (no url/paused/labels). Only `name` is required; every other field defaults to a new-template configuration. Exceeding the per-account cap returns 403 `template_limit_reached`.

## Request body

- SiteTemplateCreate: Writable fields of a site template. For PATCH, provide at least one; only the fields present are changed.
  - `name` string, nullable, required: Template name.
  - `devices` object: Device targeting split, as percentages summing to 100.
    - `desktop` integer: Percentage of visits sent to desktop devices.
    - `mobile` integer: Percentage of visits sent to mobile devices.
    - `tablet` integer: Percentage of visits sent to tablet devices.
  - `visit_duration` object: Visit duration range, in seconds.
    - `min_seconds` integer: Shortest visit duration, in seconds.
    - `max_seconds` integer: Longest visit duration, in seconds.
  - `visit_distribution` 'even' | 'asap': How visits are paced — "even" spreads them across the day, "asap" delivers as fast as possible.
  - `limits` object: Visit caps; null means no limit.
    - `hourly` integer: Max visits per hour — always at least 1 (an hourly cap is mandatory).
    - `daily` integer, nullable: Max visits per day; null means no limit.
    - `total` integer, nullable: Max visits in total (lifetime); null means no limit.
  - `schedule` object: Active-hours scheduling.
    - `active_hours_mask` string, nullable: A weekly on/off schedule: a 168-character string, one character per hour (24 hours × 7 days). Each is `1` (active that hour) or `0` (paused). The first character is Monday 00:00 and each next is the following hour, ending Sunday 23:00, in `time_zone`. `null` or all-`1`s means always on; at least one hour must be active, so an all-`0`s mask is rejected.
    - `time_zone` string, nullable: IANA time zone for the active-hours schedule (e.g. "Europe/Paris"); null uses your account timezone.
  - `location_targeting` object: Country/continent targeting.
    - `mode` 'include' | 'exclude': Whether the locations list is an allow-list (include) or a block-list (exclude).
    - `locations` object[]: The countries/continents to include or exclude.
      - `type` 'country' | 'continent': Whether code is a country or a continent.
      - `code` string: ISO country code (alpha-2) or continent code, per type.
  - `traffic_quality` object: Traffic quality controls.
    - `low_quality_ips` boolean: Whether low-quality IPs (VPN/proxy/datacenter) may deliver visits to this site.
    - `ipv6` boolean: Whether IPv6 visitors may deliver visits to this site.
  - `browsing` object: Browsing options.
    - `max_sub_windows` integer: How many pop-up windows the visited site may open during a visit.
  - `blocked_domains` object: Domains blocked during visits.
    - `rate` integer: Percentage of visits to which domain blocking applies.
    - `domains` string[]: Hostnames to block (e.g. `ads.example.com`; no scheme or path), one per entry. Up to 10.
  - `actions` object: Auto-actions performed during visits.
    - `window` 'latest' | 'first': Which opened browser window the actions target — the most recent (latest) or the first (first).
    - `items` SiteActionInput[]: The actions to perform.
      - `type` 'click' | 'click_rss' | 'click_sitemap' | 'scroll' | 'refresh', required: What the app does — click a link, click an RSS or sitemap link, scroll, or refresh.
      - `ratio` integer, required: Percentage of visits that perform this action (default 100 = every visit).
      - `element` object: Present for click-type actions.
        - `selection` 'random' | 'first' | 'last', nullable: Which element to click when several match.
        - `type` 'any' | 'internal_link' | 'external_link' | 'link' | 'button', nullable: What to click: any element, a same-domain link (`internal_link`), an off-domain link (`external_link`), any link (`link`), or a button.
        - `url_filter` string, nullable: Only click links whose URL contains this text; ignored when the element type is `button`.
        - `text_filter` string, nullable: Only click elements whose visible text contains this.
  - `cookies` SiteCookie[]: Cookies to set before each visit; replaces the stored list.
    - `name` string, required: Cookie name.
    - `value` string, required: Cookie value.
    - `domain` string, nullable: Domain to set the cookie on (a leading dot is dropped; subdomains are covered either way); null sets it on the visited site's host.
  - `traffic_sources` integer[]: IDs of traffic sources to assign.

## Response `201`

The created template.

- SiteTemplate: A reusable bundle of site settings. Mirrors a site's configuration minus the site-only fields (url, paused, blocked, labels, visit history), plus a `name`.
  - `id` integer: Unique identifier.
  - `name` string, nullable: Template name.
  - `devices` object: Device targeting split, as percentages summing to 100.
    - `desktop` integer: Percentage of visits sent to desktop devices.
    - `mobile` integer: Percentage of visits sent to mobile devices.
    - `tablet` integer: Percentage of visits sent to tablet devices.
  - `visit_duration` object: Visit duration range, in seconds.
    - `min_seconds` integer: Shortest visit duration, in seconds.
    - `max_seconds` integer: Longest visit duration, in seconds.
  - `visit_distribution` 'even' | 'asap': How visits are paced — "even" spreads them across the day, "asap" delivers as fast as possible.
  - `limits` object: Visit caps; null means no limit.
    - `hourly` integer: Max visits per hour — always at least 1 (an hourly cap is mandatory).
    - `daily` integer, nullable: Max visits per day; null means no limit.
    - `total` integer, nullable: Max visits in total (lifetime); null means no limit.
  - `schedule` object: Active-hours scheduling.
    - `active_hours_mask` string, nullable: A weekly on/off schedule: a 168-character string, one character per hour (24 hours × 7 days). Each is `1` (active that hour) or `0` (paused). The first character is Monday 00:00 and each next is the following hour, ending Sunday 23:00, in `time_zone`. `null` or all-`1`s means always on; at least one hour must be active, so an all-`0`s mask is rejected.
    - `time_zone` string, nullable: IANA time zone for the active-hours schedule (e.g. "Europe/Paris"); null uses your account timezone.
  - `traffic_quality` object: Traffic quality controls.
    - `low_quality_ips` boolean: Whether low-quality IPs (VPN/proxy/datacenter) may deliver visits to this site.
    - `ipv6` boolean: Whether IPv6 visitors may deliver visits to this site.
  - `browsing` object: Browsing options.
    - `max_sub_windows` integer: How many pop-up windows the visited site may open during a visit.
  - `location_targeting` object: Country/continent targeting.
    - `mode` 'include' | 'exclude': Whether the locations list is an allow-list (include) or a block-list (exclude).
    - `locations` object[]: The countries/continents to include or exclude.
      - `type` 'country' | 'continent': Whether code is a country or a continent.
      - `code` string: ISO country code (alpha-2) or continent code, per type.
  - `blocked_domains` object: Domains blocked during visits.
    - `rate` integer: Percentage of visits to which domain blocking applies.
    - `domains` string[]: Hostnames to block (e.g. `ads.example.com`; no scheme or path), one per entry. Up to 10.
  - `actions` object: Auto-actions performed during visits.
    - `window` 'latest' | 'first': Which opened browser window the actions target — the most recent (latest) or the first (first).
    - `items` SiteAction[]: The actions to perform.
      - `type` 'click' | 'click_rss' | 'click_sitemap' | 'scroll' | 'refresh': What the app does — click a link, click an RSS or sitemap link, scroll, or refresh.
      - `ratio` integer: Percentage of visits that perform this action (default 100 = every visit).
      - `element` object: Present for click-type actions.
        - `selection` 'random' | 'first' | 'last', nullable: Which element to click when several match.
        - `type` 'any' | 'internal_link' | 'external_link' | 'link' | 'button', nullable: What to click: any element, a same-domain link (`internal_link`), an off-domain link (`external_link`), any link (`link`), or a button.
        - `url_filter` string, nullable: Only click links whose URL contains this text; ignored when the element type is `button`.
        - `text_filter` string, nullable: Only click elements whose visible text contains this.
  - `cookies` SiteCookie[]: Cookies set before each visit.
    - `name` string, required: Cookie name.
    - `value` string, required: Cookie value.
    - `domain` string, nullable: Domain to set the cookie on (a leading dot is dropped; subdomains are covered either way); null sets it on the visited site's host.
  - `traffic_sources` integer[]: IDs of assigned traffic sources (resolve via GET /v1/traffic-sources).
  - `created_at` string, date-time, nullable: When it was created (UTC), or null.

## Other responses

- `400`: The request body was missing or not a JSON object.
- `401`: Missing or invalid API key.
- `403`: The request is not allowed. A banned or disabled account is rejected with `forbidden`; a site setting your plan does not include is rejected with `premium_required`.
- `422`: The request body failed validation.
- `429`: Too many requests — the per-account, per-minute rate limit was exceeded. Wait the number of seconds given in the `Retry-After` response header, then retry.

---

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