{"openapi":"3.0.3","info":{"title":"Guardora API","version":"1.1","description":"Управление CDN-ресурсами Guardora из вашего кода: домены, апстримы, кэш, доступ, статистика.\n\nАвторизация — API-ключ из личного кабинета (раздел «API»), заголовок `Authorization: Bearer gk_live_…`.\n\nЛимит: **120 запросов в минуту** на ключ. Все ответы и ошибки — JSON."},"servers":[{"url":"https://api.guardora.pro","description":"Продакшен"}],"tags":[{"name":"Аккаунт","description":"Ключ, баланс, сводное потребление"},{"name":"Ресурсы","description":"Создание, состояние, статистика, удаление"},{"name":"Апстримы","description":"Источники трафика ресурса"},{"name":"Кэш и настройки","description":"Режимы кэширования, HTTP/2, TLS, заголовки"},{"name":"Доступ","description":"White/black-листы по IP и CIDR"},{"name":"Редиректы","description":"Перенаправления и принудительный HTTPS"},{"name":"Домены и сертификаты","description":"Свои домены (CNAME) и выпуск TLS"}],"paths":{"/v1/ping":{"get":{"tags":["Аккаунт"],"summary":"Проверка ключа","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"schema":{"type":"object"},"example":{"ok":true,"ts":"2026-08-19T12:00:00.000Z"}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/account":{"get":{"tags":["Аккаунт"],"summary":"Профиль и квоты","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"},"example":{"email":"you@example.com","balance":2313.29,"speed_quota_mbit":100,"resource_quota":1,"resources_used":1,"billing_suspended":false,"billing_mode":"daily","package_gb_left":0}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/usage":{"get":{"tags":["Аккаунт"],"summary":"Потребление по всем ресурсам","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Usage"},"example":{"hours":24,"resources":[{"id":146,"domain":"d9yrc.guardora.pro","bytes_in":91234567,"bytes_out":88123456789,"requests":120345}],"totals":{"bytes_in":91234567,"bytes_out":88123456789,"requests":120345}}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"hours","in":"query","schema":{"type":"integer","minimum":1,"maximum":720,"default":24},"description":"Окно в часах"}]}},"/v1/resources":{"get":{"tags":["Ресурсы"],"summary":"Список ресурсов","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"schema":{"type":"object","properties":{"resources":{"type":"array","items":{"$ref":"#/components/schemas/Resource"}}}},"example":{"resources":[{"id":146,"domain":"d9yrc.guardora.pro","status":"active","protocol":"https","origin_ip":null,"dns_status":"created","dns_ips":["37.18.14.121"],"created_at":"2026-07-22T20:36:57.474Z"}]}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Ресурсы"],"summary":"Создать ресурс","security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Создано","content":{"application/json":{"schema":{"type":"object","properties":{"resource":{"$ref":"#/components/schemas/Resource"}}}}}},"400":{"description":"Некорректный origin_ip или protocol","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Нулевой баланс (no_balance) или аккаунт приостановлен (billing_suspended)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Достигнут лимит ресурсов (quota_exceeded)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Нет доступных машин (no_backend)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"description":"Выдаёт домен вида `xxxxx.guardora.pro`, DNS и сертификат. `protocol: none` — без апстрима (добавите позже).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["protocol"],"properties":{"origin_ip":{"type":"string","example":"1.2.3.4"},"protocol":{"type":"string","enum":["https","http","ws","none"]}}},"example":{"origin_ip":"1.2.3.4","protocol":"https"}}}}}},"/v1/resources/{id}":{"get":{"tags":["Ресурсы"],"summary":"Ресурс детально","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourceDetail"}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Ресурс не найден или не ваш","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"}]},"delete":{"tags":["Ресурсы"],"summary":"Удалить ресурс","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"example":{"ok":true}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Ресурс не найден","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"description":"Удаляет ресурс, его DNS-записи и сертификаты. Необратимо.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"}]}},"/v1/resources/{id}/state":{"post":{"tags":["Ресурсы"],"summary":"Включить / выключить","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"schema":{"type":"object"},"example":{"ok":true,"status":"disabled"}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Ресурс не найден","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["active","disabled"]}}},"example":{"status":"disabled"}}}}}},"/v1/resources/{id}/stats":{"get":{"tags":["Ресурсы"],"summary":"Статистика по времени","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Stats"},"example":{"bucket_sec":300,"points":[{"ts":"2026-08-19T11:00:00.000Z","bytes_in":1234567,"bytes_out":987654321,"requests":456}],"totals":{"bytes_in":1234567,"bytes_out":987654321,"requests":456}}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"description":"Корзины фиксированной ширины: 60с (≤3ч), 300с (≤24ч), 900с (≤72ч), иначе 1800с. Скорость: `байты × 8 / bucket_sec`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"},{"name":"hours","in":"query","schema":{"type":"integer","minimum":1,"maximum":168,"default":24},"description":"Окно в часах"}]}},"/v1/resources/{id}/audience":{"get":{"tags":["Ресурсы"],"summary":"Аудитория: топ IP, стран, апстримов","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Audience"}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"}]}},"/v1/resources/{id}/upstreams":{"post":{"tags":["Апстримы"],"summary":"Добавить апстрим","security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Создано","content":{"application/json":{"schema":{"type":"object","properties":{"upstream":{"$ref":"#/components/schemas/Upstream"}}}}}},"400":{"description":"Некорректные параметры","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"TCP доступен только через личный кабинет (tcp_not_granted)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Такой апстрим уже добавлен (duplicate)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpstreamInput"},"example":{"origin_ip":"1.2.3.4","port":8443,"protocol":"https","weight":1}}}}}},"/v1/resources/{id}/upstreams/{sid}":{"put":{"tags":["Апстримы"],"summary":"Изменить апстрим","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"schema":{"type":"object","properties":{"upstream":{"$ref":"#/components/schemas/Upstream"}}}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Апстрим не найден","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"description":"Частичное тело допустимо — незаданные поля берутся из текущих.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"},{"name":"sid","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpstreamInput"},"example":{"port":9443,"weight":2}}}}},"delete":{"tags":["Апстримы"],"summary":"Удалить апстрим","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"example":{"ok":true}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Апстрим не найден","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"},{"name":"sid","in":"path","required":true,"schema":{"type":"integer"}}]}},"/v1/resources/{id}/upstreams/{sid}/toggle":{"post":{"tags":["Апстримы"],"summary":"Быстро включить / выключить","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"schema":{"type":"object","properties":{"upstream":{"$ref":"#/components/schemas/Upstream"}}}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Апстрим не найден","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"},{"name":"sid","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["enabled"],"properties":{"enabled":{"type":"boolean"}}},"example":{"enabled":false}}}}}},"/v1/resources/{id}/settings":{"get":{"tags":["Кэш и настройки"],"summary":"Текущие настройки","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"schema":{"type":"object","properties":{"settings":{"$ref":"#/components/schemas/Settings"}}}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"}]},"patch":{"tags":["Кэш и настройки"],"summary":"Изменить настройки","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"schema":{"type":"object"},"example":{"ok":true}}}},"400":{"description":"Недопустимое значение (например cache_mode вне origin|cdn|off)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"description":"Передавайте только изменяемые поля.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Settings"},"example":{"cache_mode":"cdn","cache_ttl":3600,"http2":true}}}}}},"/v1/resources/{id}/cache/purge":{"post":{"tags":["Кэш и настройки"],"summary":"Очистить кэш","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"example":{"ok":true}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"description":"Мгновенно сбрасывает кэш ресурса на всех машинах.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"}]}},"/v1/resources/{id}/access":{"get":{"tags":["Доступ"],"summary":"Правила доступа","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"schema":{"type":"object","properties":{"rules":{"type":"array","items":{"$ref":"#/components/schemas/AccessRule"}}}}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"}]},"post":{"tags":["Доступ"],"summary":"Добавить правило","security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Создано","content":{"application/json":{"schema":{"type":"object","properties":{"rule":{"$ref":"#/components/schemas/AccessRule"}}}}}},"400":{"description":"Некорректный IP/CIDR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["kind","cidr"],"properties":{"kind":{"type":"string","enum":["white","black"]},"cidr":{"type":"string","example":"203.0.113.0/24"},"note":{"type":"string"}}},"example":{"kind":"black","cidr":"203.0.113.0/24","note":"сканеры"}}}}}},"/v1/resources/{id}/access/{lid}":{"delete":{"tags":["Доступ"],"summary":"Удалить правило","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"example":{"ok":true}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Правило не найдено","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"},{"name":"lid","in":"path","required":true,"schema":{"type":"integer"}}]}},"/v1/resources/{id}/redirects":{"get":{"tags":["Редиректы"],"summary":"Список редиректов","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"schema":{"type":"object","properties":{"redirects":{"type":"array","items":{"$ref":"#/components/schemas/Redirect"}}}}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"}]},"post":{"tags":["Редиректы"],"summary":"Добавить редирект","security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Создано","content":{"application/json":{"schema":{"type":"object","properties":{"redirect":{"$ref":"#/components/schemas/Redirect"}}}}}},"400":{"description":"Нужны from_path и to_url (или force_https)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"from_path":{"type":"string","example":"/old"},"to_url":{"type":"string","example":"https://example.com/new"},"code":{"type":"integer","enum":[301,302,307,308],"default":301},"force_https":{"type":"boolean","description":"Принудительный HTTPS для всего ресурса"}}},"example":{"from_path":"/old","to_url":"https://example.com/new","code":301}}}}}},"/v1/resources/{id}/redirects/{rid}":{"delete":{"tags":["Редиректы"],"summary":"Удалить редирект","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"example":{"ok":true}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Редирект не найден","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"},{"name":"rid","in":"path","required":true,"schema":{"type":"integer"}}]}},"/v1/resources/{id}/aliases":{"get":{"tags":["Домены и сертификаты"],"summary":"Привязанные домены","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"schema":{"type":"object","properties":{"aliases":{"type":"array","items":{"$ref":"#/components/schemas/Alias"}}}}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"}]},"post":{"tags":["Домены и сертификаты"],"summary":"Привязать свой домен","security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Создано","content":{"application/json":{"schema":{"type":"object","properties":{"alias":{"$ref":"#/components/schemas/Alias"},"hint":{"type":"string"}}}}}},"400":{"description":"Некорректный домен","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Домен уже добавлен (duplicate)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"description":"Заранее направьте CNAME вашего домена на домен ресурса. Если CNAME ещё не виден — алиас создастся в статусе `pending`, затем вызовите `/check`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["domain"],"properties":{"domain":{"type":"string","example":"cdn.example.com"}}},"example":{"domain":"cdn.example.com"}}}}}},"/v1/resources/{id}/aliases/{aid}/check":{"post":{"tags":["Домены и сертификаты"],"summary":"Проверить CNAME и активировать","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"schema":{"type":"object","properties":{"alias":{"$ref":"#/components/schemas/Alias"}}}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Домен не найден","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"},{"name":"aid","in":"path","required":true,"schema":{"type":"integer"}}]}},"/v1/resources/{id}/aliases/{aid}":{"delete":{"tags":["Домены и сертификаты"],"summary":"Отвязать домен","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"example":{"ok":true}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Домен не найден","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"},{"name":"aid","in":"path","required":true,"schema":{"type":"integer"}}]}},"/v1/resources/{id}/certs":{"post":{"tags":["Домены и сертификаты"],"summary":"Перевыпустить сертификат","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Успех","content":{"application/json":{"schema":{"type":"object"},"example":{"status":"issued","domain":"d9yrc.guardora.pro"}}}},"401":{"description":"Нет ключа, ключ неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Домен не относится к ресурсу","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Превышен лимит запросов (Retry-After: 60)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Выпуск не удался (cert_failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"description":"Не чаще 5 раз в минуту. `domain` не указан — домен самого ресурса.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"ID ресурса"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"domain":{"type":"string"}}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"gk_live_…","description":"API-ключ из личного кабинета (раздел «API»)"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string","example":"Описание ошибки"},"code":{"type":"string","example":"bad_request"}}},"Account":{"type":"object","properties":{"email":{"type":"string"},"balance":{"type":"number"},"speed_quota_mbit":{"type":"integer"},"resource_quota":{"type":"integer"},"resources_used":{"type":"integer"},"billing_suspended":{"type":"boolean"},"billing_mode":{"type":"string","enum":["daily","traffic","package"]},"package_gb_left":{"type":"number"}}},"Resource":{"type":"object","properties":{"id":{"type":"integer"},"domain":{"type":"string"},"status":{"type":"string","enum":["active","disabled"]},"protocol":{"type":"string"},"origin_ip":{"type":"string","nullable":true},"dns_status":{"type":"string"},"dns_ips":{"type":"array","items":{"type":"string"}},"created_at":{"type":"string","format":"date-time"}}},"ResourceDetail":{"type":"object","properties":{"resource":{"$ref":"#/components/schemas/Resource"},"upstreams":{"type":"array","items":{"$ref":"#/components/schemas/Upstream"}},"certs":{"type":"array","items":{"type":"object","properties":{"domain":{"type":"string"},"status":{"type":"string"},"expires_at":{"type":"string","nullable":true}}}}}},"Upstream":{"type":"object","properties":{"id":{"type":"integer"},"origin_ip":{"type":"string"},"port":{"type":"integer"},"listen_port":{"type":"integer"},"protocol":{"type":"string"},"origin_host":{"type":"string","nullable":true},"use_tls":{"type":"boolean"},"tls_insecure":{"type":"boolean"},"weight":{"type":"integer"},"enabled":{"type":"boolean"},"proxy_protocol":{"type":"boolean"}}},"UpstreamInput":{"type":"object","required":["origin_ip","port"],"properties":{"origin_ip":{"type":"string"},"port":{"type":"integer"},"protocol":{"type":"string","enum":["https","http","ws"],"default":"https"},"origin_host":{"type":"string"},"use_tls":{"type":"boolean"},"tls_insecure":{"type":"boolean"},"weight":{"type":"integer","default":1},"proxy_protocol":{"type":"boolean"},"enabled":{"type":"boolean","default":true}}},"Settings":{"type":"object","properties":{"cache_mode":{"type":"string","enum":["origin","cdn","off"]},"cache_ttl":{"type":"integer","minimum":0,"maximum":2592000},"cache_query_keys":{"type":"string","description":"Ключи query, участвующие в кэше"},"client_no_cache":{"type":"boolean"},"http2":{"type":"boolean"},"compression":{"type":"object"},"tls_versions":{"type":"array","items":{"type":"string","enum":["TLSv1.2","TLSv1.3"]}},"cors_allow_origin":{"type":"string","nullable":true},"client_ip_header":{"type":"string"},"upstream_headers":{"type":"object"},"client_headers":{"type":"object"}}},"Stats":{"type":"object","properties":{"bucket_sec":{"type":"integer"},"points":{"type":"array","items":{"type":"object","properties":{"ts":{"type":"string","format":"date-time"},"bytes_in":{"type":"integer"},"bytes_out":{"type":"integer"},"requests":{"type":"integer"}}}},"totals":{"type":"object","properties":{"bytes_in":{"type":"integer"},"bytes_out":{"type":"integer"},"requests":{"type":"integer"}}}}},"Usage":{"type":"object","properties":{"hours":{"type":"integer"},"resources":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"domain":{"type":"string"},"bytes_in":{"type":"integer"},"bytes_out":{"type":"integer"},"requests":{"type":"integer"}}}},"totals":{"type":"object","properties":{"bytes_in":{"type":"integer"},"bytes_out":{"type":"integer"},"requests":{"type":"integer"}}}}},"Audience":{"type":"object","properties":{"top_ips":{"type":"array","items":{"type":"object","properties":{"ip":{"type":"string"},"country":{"type":"string","nullable":true},"requests":{"type":"integer"},"bytes_out":{"type":"integer"}}}},"top_locations":{"type":"array","items":{"type":"object","properties":{"country":{"type":"string","nullable":true},"requests":{"type":"integer"},"ips":{"type":"integer"}}}},"top_upstreams":{"type":"array","items":{"type":"object","properties":{"origin":{"type":"string"},"requests":{"type":"integer"},"bytes_out":{"type":"integer"}}}}}},"AccessRule":{"type":"object","properties":{"id":{"type":"integer"},"kind":{"type":"string","enum":["white","black"]},"cidr":{"type":"string"},"note":{"type":"string","nullable":true}}},"Redirect":{"type":"object","properties":{"id":{"type":"integer"},"from_path":{"type":"string"},"to_url":{"type":"string"},"code":{"type":"integer"},"force_https":{"type":"boolean"}}},"Alias":{"type":"object","properties":{"id":{"type":"integer"},"domain":{"type":"string"},"status":{"type":"string","enum":["active","pending"]},"source":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}}}}}