Skip to content

Documentation

Create scenario

POST /api/v1/scripts

Create a scenario entry. Its source code is saved in a separate version.

Access

A Bearer API key for this workspace with write permission is required. The server also checks the owner’s permission for this resource and action. An inaccessible object is not disclosed.

Parameters

Example request parameters or JSON body:

{
  "site_id": 1,
  "code": "catalog-main",
  "name": "Catalog collection",
  "entry": "run"
}

site_id and name are required. entry defaults to run. code is optional; when supplied, it uses lowercase Latin letters, digits, and hyphens. A template may accept template and inputs to create a draft. Check the template input definition before sending values.

Response 201

The example is shortened; actual responses may include more fields. Sample IDs are placeholders.

{
  "id": 2,
  "site": {
    "id": 1,
    "code": "catalog"
  },
  "code": "catalog-main",
  "name": "Catalog collection",
  "entry": "run",
  "published_version": null,
  "versions_count": 0
}

Send the request

Set BASE to your installation URL without a trailing slash and API_KEY to a secret stored on your server. Client setup and browser JavaScript.

curl

curl --fail-with-body -X POST "$BASE/api/v1/scripts" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{
  "site_id": 1,
  "code": "catalog-main",
  "name": "Catalog collection",
  "entry": "run"
}
JSON

Node.js · server

// Node.js server example. Save as request.mjs.
const response = await fetch(process.env.BASE + "/api/v1/scripts", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.API_KEY}`,
    Accept: "application/json",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({"site_id":1,"code":"catalog-main","name":"Catalog collection","entry":"run"}),
  signal: AbortSignal.timeout(120000)
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
console.log(await response.json());

Python

import json
import os
import urllib.request
import urllib.error

body = '{"site_id":1,"code":"catalog-main","name":"Catalog collection","entry":"run"}'.encode("utf-8")
request = urllib.request.Request(
    os.environ["BASE"] + "/api/v1/scripts",
    method="POST",
    headers={"Authorization": "Bearer " + os.environ["API_KEY"],
             "Accept": "application/json", "Content-Type": "application/json"},
    data=body,
)
try:
    with urllib.request.urlopen(request, timeout=120) as response:
        print(json.load(response))
except urllib.error.HTTPError as error:
    print(error.code, error.read().decode("utf-8", errors="replace"))
    raise

PHP · external client

<?php
$handle = curl_init(getenv("BASE") . "/api/v1/scripts");
curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 120,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("API_KEY"),
        "Accept: application/json",
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => <<<'JSON'
{"site_id":1,"code":"catalog-main","name":"Catalog collection","entry":"run"}
JSON,
]);
$content = curl_exec($handle);
$status = curl_getinfo($handle, CURLINFO_RESPONSE_CODE);
if ($content === false) {
    throw new RuntimeException(curl_error($handle));
}
curl_close($handle);
if ($status < 200 || $status >= 300) {
    throw new RuntimeException("HTTP $status: $content");
}
print_r(json_decode($content, true, 512, JSON_THROW_ON_ERROR));

Go

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
    "time"
    "strings"
)

func main() {
    body := strings.NewReader(`{"site_id":1,"code":"catalog-main","name":"Catalog collection","entry":"run"}`)
    request, err := http.NewRequest("POST", os.Getenv("BASE") + "/api/v1/scripts", body)
    if err != nil { panic(err) }
    request.Header.Set("Authorization", "Bearer " + os.Getenv("API_KEY"))
    request.Header.Set("Accept", "application/json")
    request.Header.Set("Content-Type", "application/json")
    client := &http.Client{Timeout: 120 * time.Second}
    response, err := client.Do(request)
    if err != nil { panic(err) }
    defer response.Body.Close()
    content, err := io.ReadAll(response.Body)
    if err != nil { panic(err) }
    if response.StatusCode < 200 || response.StatusCode >= 300 {
        panic(fmt.Sprintf("HTTP %d: %s", response.StatusCode, content))
    }
    fmt.Println(string(content))
}

If the request fails

401: check the key and its expiry. 403: check permissions, read/write scope, and 2FA. 404: check the ID and workspace. 422: check fields and resource state. 429: respect Retry-After. Errors and retries.

More creation options

You can omit code; the platform generates an identifier. name is required, while description is optional. For an available template, send template and an inputs object. The template description lists the input fields, types, and defaults. For example, a Wildberries template accepts products and regions:

{"site_id":22,"name":"Prices in two cities","template":"wildberries-products:wb-products","inputs":{"products":["622592787"],"regions":["moscow","saint-petersburg"]}}

For a custom address, a list item has the form custom:12345|Your label. Obtain the number for your own delivery address; do not copy it from this example. The server checks the domain, template availability, site fields, and input values. It creates a draft without publishing it automatically. The older products[] field remains supported.