Вступ
Це сторінка документації API KWIGA. За допомогою API ви можете виконувати дії від свого імені в ваших кабінетах KWIGA — кабінет це ваш робочий простір (акаунт / тенант), де живуть ваші курси, контакти та решта даних.
Для того щоб увімкнути API, в особистому кабінеті в розділі settings потрібно відмітити відповідний чекбокс. Після цього буде згенерований токен для API та отриманий хеш кабінету, які потрібні для подальших звернень до API.
При компрометації токена його можна перевипустити, що зробить минулий токен неактивним і згенерує новий.
API доступний тільки для тих користувачів, у кого в кабінеті включено API.
Обмеження частоти запитів
API має обмеження на кількість звернень 200 запитів на хвилину. Ліміт рахується окремо для кожного API-токена.
У кожній відповіді повертаються такі заголовки з інформацією про ліміт:
| Заголовок | Опис |
|---|---|
X-RateLimit-Limit |
максимальна кількість запитів на хвилину. |
X-RateLimit-Remaining |
скільки запитів ще доступно в поточній хвилині. |
Retry-After |
через скільки секунд можна повторити запит. Повертається лише при перевищенні ліміту (HTTP 429). |
X-RateLimit-Reset |
UNIX timestamp, коли скидається поточне вікно. Повертається лише при перевищенні ліміту (HTTP 429). |
Ідемпотентність
Мутуючі ендпоінти публічного API (зараз POST /contacts/:contact/rewards; інші будуть позначатися індивідуально) приймають опціональний header Idempotency-Key. Передайте унікальне значення один раз і використовуйте його на кожному ретраї тієї ж логічної операції — сервер «згорне» повтори в один сайд-ефект і на кожен ретрай поверне ту ж відповідь.
Ендпоінти, що підтримують ідемпотентність, позначені в цій документації плашкою: Ідемпотентний
Контракт:
| Header | Поведінка |
|---|---|
Idempotency-Key (request) |
Унікальний рядок від клієнта (1–255 символів). Підійде UUIDv4 або стабільний бізнес-ключ типу reward-for-quiz-attempt-4821. Порожній/відсутній header вимикає ідемпотентність для цього виклику. Клієнти, які не можуть передавати кастомні headers (form-based інтеграції), можуть передати те саме значення як поле body/query idempotency_key — header має пріоритет, якщо передані обидва. |
Idempotent-Replayed: true (response) |
Повертається на другому та подальших викликах з тим самим ключем. Якщо бачите цей header — сервер НЕ виконував операцію повторно, body містить той самий обʼєкт, що був створений при першому виклику (сутність перечитується та серіалізується заново, тому відображає свій поточний стан). Якщо цю сутність на цей момент було видалено остаточно, body — це мінімальне підтвердження з її типом та id. |
Область ключа — (кабінет, ендпоінт, ключ): той же бізнес-ключ на іншому ендпоінті або в іншому кабінеті вважається окремою операцією. Рекомендуємо все одно UUIDv4 — колізії стають статистично неможливими.
Базова робота з API
<?php
// Get contact by ID
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/contacts/:contact', $options);
$result = json_decode($response->getBody());
?>
<?php
// Get contact by ID
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/:contact');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request GET 'https://api.kwiga.com/contacts/:contact' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// Get contact by ID
const url = 'https://api.kwiga.com/contacts/:contact';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Get contact by ID
import requests
url = 'https://api.kwiga.com/contacts/:contact'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
{
"method": "GET",
"url": "https://api.kwiga.com/contacts/:contact",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Всі запити повинні надсилатися на домен:
https://api.kwiga.com
Для авторизації передаємо API-токен в одному з варіантів:
в заголовках:
Token: {token}в GET/POST параметрах:
token={token}
Для ідентифікації кабінету, в якому відбуваються дії, обов'язково передаємо хеш-кабінету в одному з варіантів:
в заголовках:
Cabinet-Hash: {cabinet_hash}в GET/POST параметрах:
cabinet_hash={cabinet_hash}
PUT та DELETE запити можна надсилати POST-запитом із зазначенням додаткового параметра _method з потрібним методом (PUT або DELETE).
Встановити локалізацію довідників та повідомлень валідації можна заголовком:
X-Language: {locale}
| Locale | Description |
|---|---|
| en | English (default) |
| cs | Czech |
| de | German |
| el | Greek |
| es | Spanish |
| fr | Franch |
| hu | Hungarian |
| it | Italian |
| ka | Georgian |
| lv | Polish |
| pl | Polish |
| pt | Portuguese |
| ro | Romanian |
| ru | Russian |
| uk | Ukrainian |
| zh | Chinese (Simplified) |
Помилки
| Код помилки | Значення |
|---|---|
| 400 | Bad Request - Ваш запит невірний. |
| 401 | Unauthorized - Ваш API-ключ невірний. |
| 403 | Forbidden - Запитаний ресурс захован та доступний лише адміністраторам. |
| 404 | Not Found - Не знайдено. Вказана сторінка не знайдена. |
| 405 | Method Not Allowed - Метод не дозволений. Серверу відомий метод запиту, але цільовий ресурс не підтримує цей метод. |
| 422 | Unprocessable entity - Сутність неможливо обробити. |
| 429 | Too Many Requests - Дуже багато запитів - Ви надсилаєте надто багато запитів, зупиніться! |
| 500 | Internal Server Error - Внутрішня помилка сервера. Проблема із нашим сервером. Повторіть спробу пізніше. |
| 503 | Service Unavailable - ми тимчасово відключені від мережі через технічне обслуговування. Повторіть спробу пізніше. |
CRM. Контакти
Картки контактів
Список контактів
Приклад запиту:
<?php
// Get contacts list
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/contacts', $options);
$result = json_decode($response->getBody());
?>
# ---
# Paginated example
# ---
<?php
// Get contacts list with pagination
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/contacts?page=1&per_page=15', $options);
$result = json_decode($response->getBody());
?>
# ---
# Filtered example
# ---
<?php
// Get contacts list with filters
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/contacts?page=1&per_page=15&filters[date_from]=2022-04-27&filters[search]=example.com&with_offers=1', $options);
$result = json_decode($response->getBody());
?>
<?php
// Get contacts list
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
# ---
# Paginated example
# ---
<?php
// Get contacts list with pagination
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts?page=1&per_page=15');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
# ---
# Filtered example
# ---
<?php
// Get contacts list with filters
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts?page=1&per_page=15&filters[date_from]=2022-04-27&filters[search]=example.com&with_offers=1');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request GET 'https://api.kwiga.com/contacts' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
# ---
# Paginated example
# ---
curl --location --request GET 'https://api.kwiga.com/contacts?page=1&per_page=15' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
# ---
# Filtered example
# ---
curl --location --request GET 'https://api.kwiga.com/contacts?page=1&per_page=15&filters[date_from]=2022-04-27&filters[search]=example.com&with_offers=1' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// Get contacts list
const url = 'https://api.kwiga.com/contacts';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# ---
# Paginated example
# ---
// Get contacts list with pagination
const url = 'https://api.kwiga.com/contacts?page=1&per_page=15';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# ---
# Filtered example
# ---
// Get contacts list with filters
const url = 'https://api.kwiga.com/contacts?page=1&per_page=15&filters[date_from]=2022-04-27&filters[search]=example.com&with_offers=1';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Get contacts list
import requests
url = 'https://api.kwiga.com/contacts'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
# ---
# Paginated example
# ---
# Get contacts list with pagination
import requests
url = 'https://api.kwiga.com/contacts?page=1&per_page=15'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
# ---
# Filtered example
# ---
# Get contacts list with filters
import requests
url = 'https://api.kwiga.com/contacts?page=1&per_page=15&filters[date_from]=2022-04-27&filters[search]=example.com&with_offers=1'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
{
"method": "GET",
"url": "https://api.kwiga.com/contacts",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
# ---
# Paginated example
# ---
{
"method": "GET",
"url": "https://api.kwiga.com/contacts?page=1&per_page=15",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
# ---
# Filtered example
# ---
{
"method": "GET",
"url": "https://api.kwiga.com/contacts?page=1&per_page=15&filters[date_from]=2022-04-27&filters[search]=example.com&with_offers=1",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Приклад відповіді:
{
"data": [
{
"id": 1,
"created_at": "2022-02-04T12:17:32.000000Z",
"email": "test@example.com",
"first_name": "James",
"last_name": "Bond",
"phone": "+380931234567",
"tags": [
{
"id": 93,
"name": "test-tag"
}
],
"offers": [
{
"id": 8,
"unique_offer_code": "ptJmPPXVYs0t",
"title": "Предложение #8",
"limit_type": {
"id": 1,
"name": "Неограничено"
},
"limit_of_sales": null
}
]
},
"utm": {
"utm_source": [
"test-source"
],
"utm_campaign": [],
"utm_medium": [],
"utm_term": [
"test-term"
],
"utm_content": []
},
{
"id": 2,
"created_at": "2022-02-04T12:17:32.000000Z",
"email": "test2@example.com",
"first_name": "Petr",
"last_name": "Ivanov",
"phone": "+380983234512",
"tags": [],
"offers": []
}
],
"links": {
"first": "https://api.kwiga.com/contacts?page=1",
"last": "https://api.kwiga.com/contacts?page=2",
"prev": null,
"next": "https://api.kwiga.com/contacts?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 2,
"links": [
{
"url": null,
"label": "« translation missing: ua.pagination_prev",
"active": false
},
{
"url": "https://api.kwiga.com/contacts?page=1",
"label": "1",
"active": true
},
{
"url": "https://api.kwiga.com/contacts?page=2",
"label": "2",
"active": false
},
{
"url": "https://api.kwiga.com/contacts?page=2",
"label": "translation missing: ua.pagination_next »",
"active": false
}
],
"path": "https://api.kwiga.com/contacts",
"per_page": 15,
"to": 2,
"total": 3
}
}
GET https://api.kwiga.com/contacts
URL Parameters
115asc, descDefault: descСтруктура відповіді
POST-аліас
POST https://api.kwiga.com/contacts/query
Функціональний аліас для GET-ендпоінта вище. Приймає ті самі параметри в тілі запиту замість query-string — стане в нагоді, коли список фільтрів завеликий для URL (або просто зручніше збирати JSON на клієнті). Body має пріоритет над query-string, форма відповіді ідентична.
Отримання контакту
Приклад запиту:
<?php
// Get contact by ID
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/contacts/:contact', $options);
$result = json_decode($response->getBody());
?>
<?php
// Get contact by ID
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/:contact');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request GET 'https://api.kwiga.com/contacts/:contact' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// Get contact by ID
const url = 'https://api.kwiga.com/contacts/:contact';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Get contact by ID
import requests
url = 'https://api.kwiga.com/contacts/:contact'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
{
"method": "GET",
"url": "https://api.kwiga.com/contacts/:contact",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Приклад відповіді:
{
"data": {
"id": 132,
"email": "bond@example.com",
"first_name": "James",
"last_name": "Bond",
"phone_number": "931234567",
"tags": [],
"created_at": "2023-06-26T19:01:00.000000Z",
"additional_fields": [
{
"id": 110,
"field": {
"id": 17,
"title": "test global",
"is_local": false
},
"value": "this is test value"
}
]
}
}
GET https://api.kwiga.com/contacts/:contact
URL Parameters
Структура відповіді
Створення контакту
Приклад запиту:
<?php
// Create new contact
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
'json' => [
'first_name' => 'James',
'last_name' => 'Bond',
'email' => 'bond@example.com',
'send_activation_email' => true,
'phone' => '+380931234567',
'manager_ids' => [264, 288],
'additional_fields' => [{"field_id"=>17, "value"=>"this is test value"}],
],
];
$response = $client->request('POST', '/contacts', $options);
$result = json_decode($response->getBody());
?>
<?php
// Create new contact
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$data = [
'first_name' => 'James',
'last_name' => 'Bond',
'email' => 'bond@example.com',
'send_activation_email' => true,
'phone' => '+380931234567',
'manager_ids' => [264, 288],
'additional_fields' => [{"field_id"=>17, "value"=>"this is test value"}],
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request POST 'https://api.kwiga.com/contacts' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>' \
--data-raw '{"first_name":"James","last_name":"Bond","email":"bond@example.com","send_activation_email":true,"phone":"+380931234567","manager_ids":[264,288],"additional_fields":[{"field_id":17,"value":"this is test value"}]}'
// Create new contact
const url = 'https://api.kwiga.com/contacts';
const options = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
body: JSON.stringify({
'first_name': 'James',
'last_name': 'Bond',
'email': 'bond@example.com',
'send_activation_email': true,
'phone': '+380931234567',
'manager_ids': [264, 288],
'additional_fields': [{"field_id"=>17, "value"=>"this is test value"}]
})
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Create new contact
import requests
url = 'https://api.kwiga.com/contacts'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
data = {
'first_name': 'James',
'last_name': 'Bond',
'email': 'bond@example.com',
'send_activation_email': true,
'phone': '+380931234567',
'manager_ids': [264, 288],
'additional_fields': [{"field_id"=>17, "value"=>"this is test value"}],
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
{
"method": "POST",
"url": "https://api.kwiga.com/contacts",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"first_name": "James",
"last_name": "Bond",
"email": "bond@example.com",
"send_activation_email": true,
"phone": "+380931234567",
"manager_ids": [
264,
288
],
"additional_fields": [
{
"field_id": 17,
"value": "this is test value"
}
]
}
}
Приклад відповіді:
{
"data": {
"id": 132,
"email": "bond@example.com",
"first_name": "James",
"last_name": "Bond",
"phone_number": "931234567",
"tags": [],
"created_at": "2023-06-26T19:01:00.000000Z",
"additional_fields": [
{
"id": 110,
"field": {
"id": 17,
"title": "test global",
"is_local": false
},
"value": "this is test value"
}
]
}
}
POST https://api.kwiga.com/contacts
Request
falseenСтруктура відповіді
Оновлення контакту
Приклад запиту:
<?php
// Update contact
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
'json' => [
'first_name' => 'John',
'last_name' => 'Black',
'email' => 'bond123@example.com',
'phone' => '+380931112233',
'tags' => ["test-tag"],
],
];
$response = $client->request('PUT', '/contacts/:contact', $options);
$result = json_decode($response->getBody());
?>
<?php
// Update contact
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/:contact');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
$data = [
'first_name' => 'John',
'last_name' => 'Black',
'email' => 'bond123@example.com',
'phone' => '+380931112233',
'tags' => ["test-tag"],
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request PUT 'https://api.kwiga.com/contacts/:contact' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>' \
--data-raw '{"first_name":"John","last_name":"Black","email":"bond123@example.com","phone":"+380931112233","tags":["test-tag"]}'
// Update contact
const url = 'https://api.kwiga.com/contacts/:contact';
const options = {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
body: JSON.stringify({
'first_name': 'John',
'last_name': 'Black',
'email': 'bond123@example.com',
'phone': '+380931112233',
'tags': ["test-tag"]
})
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Update contact
import requests
url = 'https://api.kwiga.com/contacts/:contact'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
data = {
'first_name': 'John',
'last_name': 'Black',
'email': 'bond123@example.com',
'phone': '+380931112233',
'tags': ["test-tag"],
}
response = requests.put(url, headers=headers, json=data)
result = response.json()
{
"method": "PUT",
"url": "https://api.kwiga.com/contacts/:contact",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"first_name": "John",
"last_name": "Black",
"email": "bond123@example.com",
"phone": "+380931112233",
"tags": [
"test-tag"
]
}
}
Приклад відповіді:
{
"data": {
"id": 132,
"email": "bond@example.com",
"first_name": "James",
"last_name": "Bond",
"phone_number": "931234567",
"tags": [],
"created_at": "2023-06-26T19:01:00.000000Z",
"additional_fields": [
{
"id": 110,
"field": {
"id": 17,
"title": "test global",
"is_local": false
},
"value": "this is test value"
}
]
}
}
PUT https://api.kwiga.com/contacts/:contact
Request
Структура відповіді
Додати покупку
Цей метод створює або знаходить контакт и додає йому покупку пропозиції
Приклад запиту:
<?php
// Add purchase to contact
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
'json' => [
'first_name' => 'James',
'last_name' => 'Bond',
'email' => 'bond@example.com',
'send_activation_email' => true,
'phone' => '+380931234567',
'offer_id' => 18,
'additional_fields' => [{"field_id"=>17, "value"=>"this is test value"}],
],
];
$response = $client->request('POST', '/contacts/purchases', $options);
$result = json_decode($response->getBody());
?>
<?php
// Add purchase to contact
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/purchases');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$data = [
'first_name' => 'James',
'last_name' => 'Bond',
'email' => 'bond@example.com',
'send_activation_email' => true,
'phone' => '+380931234567',
'offer_id' => 18,
'additional_fields' => [{"field_id"=>17, "value"=>"this is test value"}],
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request POST 'https://api.kwiga.com/contacts/purchases' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>' \
--data-raw '{"first_name":"James","last_name":"Bond","email":"bond@example.com","send_activation_email":true,"phone":"+380931234567","offer_id":18,"additional_fields":[{"field_id":17,"value":"this is test value"}]}'
// Add purchase to contact
const url = 'https://api.kwiga.com/contacts/purchases';
const options = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
body: JSON.stringify({
'first_name': 'James',
'last_name': 'Bond',
'email': 'bond@example.com',
'send_activation_email': true,
'phone': '+380931234567',
'offer_id': 18,
'additional_fields': [{"field_id"=>17, "value"=>"this is test value"}]
})
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Add purchase to contact
import requests
url = 'https://api.kwiga.com/contacts/purchases'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
data = {
'first_name': 'James',
'last_name': 'Bond',
'email': 'bond@example.com',
'send_activation_email': true,
'phone': '+380931234567',
'offer_id': 18,
'additional_fields': [{"field_id"=>17, "value"=>"this is test value"}],
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
{
"method": "POST",
"url": "https://api.kwiga.com/contacts/purchases",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"first_name": "James",
"last_name": "Bond",
"email": "bond@example.com",
"send_activation_email": true,
"phone": "+380931234567",
"offer_id": 18,
"additional_fields": [
{
"field_id": 17,
"value": "this is test value"
}
]
}
}
Приклад відповіді:
{
"data": {
"id": 132,
"email": "bond@example.com",
"first_name": "James",
"last_name": "Bond",
"phone_number": "931234567",
"tags": [],
"created_at": "2023-06-26T19:01:00.000000Z",
"additional_fields": [
{
"id": 110,
"field": {
"id": 17,
"title": "test global",
"is_local": false
},
"value": "this is test value"
}
],
"orders": [
{
"id": 1060,
"type_id": 1,
"first_paid_at": "2023-10-13T18:04:02.000000Z",
"paid_at": "2023-10-13T18:04:02.000000Z",
"created_at": "2023-10-13T18:04:02.000000Z",
"updated_at": "2023-10-13T18:04:02.000000Z",
"products": [
{
"id": 25,
"productable_id": 10,
"productable_type": "course",
"title": "test course",
"url": "https://sample-school.kwiga.com/courses/test-course"
}
],
"payments": [
{
"id": 1231,
"status": 2,
"status_title": "Paid",
"payment_type": null,
"payment_type_title": null,
"payment_form": null,
"payment_form_title": null,
"price_info": {
"amount": 0,
"currency": {
"id": 147,
"code": "UAH",
"html_code": "₴",
"html_letter_code": "грн"
}
},
"paid_at": "2023-10-13T18:04:02.000000Z",
"created_at": "2023-10-13T18:04:02.000000Z",
"updated_at": "2023-10-13T18:04:02.000000Z",
"transactions": [
{
"id": 28,
"merchant_id": 2,
"payment_id": 1231,
"order_id": 1060,
"payment_system_status": "Declined",
"failure_reason": "Cardholder session expired",
"price": "147",
"currency_code": "UAH",
"payer_account": null,
"card_mask": null,
"rrn": null,
"fee": null,
"created_at": "2023-11-03T08:45:10.000000Z"
},
{
"id": 29,
"merchant_id": 2,
"payment_id": 1231,
"order_id": 1060,
"payment_system_status": "Approved",
"failure_reason": null,
"price": "147",
"currency_code": "UAH",
"payer_account": "JKNNASWTZ99SJ",
"card_mask": "53****2144",
"rrn": 330710335365,
"fee": null,
"created_at": "2023-11-03T08:48:10.000000Z"
}
]
}
],
"paid_status": "paid",
"paid_status_title": "Сплачено",
"order_stage": {
"id": 43,
"title": "Стейдж 1",
"order_group": {
"id": 22,
"slug": "voronka-1",
"title": null,
"order": 4,
"created_at": "2023-06-22T18:20:53.000000Z"
},
"order_funnel": {
"id": 1,
"title": "Воронка за замовчуванням",
"created_at": "2023-05-26T09:47:16.000000Z"
},
"created_at": "2023-06-22T18:21:10.000000Z"
},
"cost_info": {
"amount": 0,
"currency": {
"id": 147,
"code": "UAH",
"html_code": "₴",
"html_letter_code": "грн"
}
},
"managers": [
{
"id": 264,
"name": "test",
"email": "testfsdf@fdafasd.fsd"
},
{
"id": 288,
"name": "fdsf",
"email": "sdfs@fdf.dfss"
}
]
}
]
}
}
POST https://api.kwiga.com/contacts/purchases
Request
falsefalsefalseenhttps://sample-school.kwiga.com/expert/payments/offers/edit/3858). Якщо не переданий — запит звертається до поля product_ids.
Якщо offer_id і product_ids відсутні, то буде створено пусте замовлення
trueСтруктура відповіді
Теги
Додавання тегів контактам
Приклад запиту:
<?php
// Add tags to contacts
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
'json' => [
'contacts' => [23698],
'tags' => ["test-tag"],
],
];
$response = $client->request('POST', '/contacts/tags', $options);
$result = json_decode($response->getBody());
?>
<?php
// Add tags to contacts
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/tags');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$data = [
'contacts' => [23698],
'tags' => ["test-tag"],
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request POST 'https://api.kwiga.com/contacts/tags' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>' \
--data-raw '{"contacts":[23698],"tags":["test-tag"]}'
// Add tags to contacts
const url = 'https://api.kwiga.com/contacts/tags';
const options = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
body: JSON.stringify({
'contacts': [23698],
'tags': ["test-tag"]
})
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Add tags to contacts
import requests
url = 'https://api.kwiga.com/contacts/tags'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
data = {
'contacts': [23698],
'tags': ["test-tag"],
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
{
"method": "POST",
"url": "https://api.kwiga.com/contacts/tags",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"contacts": [
23698
],
"tags": [
"test-tag"
]
}
}
Приклад відповіді:
{
"success": true
}
POST https://api.kwiga.com/contacts/tags
Request
contact_ids. Збережений заради зворотної сумісності; у нових інтеграціях використовуйте contact_ids.
Структура відповіді
Видалення тегів контактів
Приклад запиту:
<?php
// Remove tags from contacts
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
'json' => [
'contacts' => [23698],
'tags' => ["test-tag"],
],
];
$response = $client->request('DELETE', '/contacts/tags', $options);
$result = json_decode($response->getBody());
?>
<?php
// Remove tags from contacts
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/tags');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
$data = [
'contacts' => [23698],
'tags' => ["test-tag"],
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request DELETE 'https://api.kwiga.com/contacts/tags' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>' \
--data-raw '{"contacts":[23698],"tags":["test-tag"]}'
// Remove tags from contacts
const url = 'https://api.kwiga.com/contacts/tags';
const options = {
method: 'DELETE',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
body: JSON.stringify({
'contacts': [23698],
'tags': ["test-tag"]
})
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Remove tags from contacts
import requests
url = 'https://api.kwiga.com/contacts/tags'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
data = {
'contacts': [23698],
'tags': ["test-tag"],
}
response = requests.delete(url, headers=headers, json=data)
result = response.json()
{
"method": "DELETE",
"url": "https://api.kwiga.com/contacts/tags",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"contacts": [
23698
],
"tags": [
"test-tag"
]
}
}
Приклад відповіді:
{
"success": true
}
DELETE https://api.kwiga.com/contacts/tags
Request
contact_ids. Збережений заради зворотної сумісності; у нових інтеграціях використовуйте contact_ids.
Структура відповіді
Продукти та підписки
Список продуктів контакту
Приклад запиту:
<?php
// Get contact products
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/contacts/:contact/products', $options);
$result = json_decode($response->getBody());
?>
<?php
// Get contact products
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/:contact/products');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request GET 'https://api.kwiga.com/contacts/:contact/products' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// Get contact products
const url = 'https://api.kwiga.com/contacts/:contact/products';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Get contact products
import requests
url = 'https://api.kwiga.com/contacts/:contact/products'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
{
"method": "GET",
"url": "https://api.kwiga.com/contacts/:contact/products",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Приклад відповіді:
{
"data": [
{
"id": 299,
"productable_id": 142,
"productable_type": "course",
"title": "Copy Test backup",
"image_url": "",
"is_published": false,
"aggregated_subscription": {
"is_active": true,
"is_paid": true,
"start_at": "2025-05-05T15:09:04.000000Z",
"end_at": null,
"offer_end_at": null,
"order_end_at": null,
"count_available_days": 39,
"count_left_days": null,
"state": {
"id": 2,
"name": "Open",
"title": "Open"
}
},
"subscriptions": [
{
"id": 4775,
"creator_id": 24457,
"user_id": 24457,
"product_id": 299,
"order_id": 2710,
"offer_id": 757,
"is_active": true,
"start_at": "2025-05-05T15:09:04.000000Z",
"order_end_at": null,
"end_at": null,
"paid_at": "2025-05-05T15:09:04.000000Z",
"created_at": "2025-05-05T15:09:04.000000Z",
"updated_at": "2025-05-05T15:09:04.000000Z"
}
]
}
]
}
GET https://api.kwiga.com/contacts/:contact/products
Повертає список продуктів контакту з інформацією про підписки та терміни доступу. Параметр aggregated_subscription містить зведену інформацію про терміни та активність доступу на основі всіх підписок користувача по продукту. Параметр subscriptions містить масив всіх підписок користувача по продукту.
Структура відповіді
Видалити продукт у контакта
Приклад запиту:
<?php
// Delete contact product
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('DELETE', '/contacts/:contact/products/:product', $options);
$result = json_decode($response->getBody());
?>
<?php
// Delete contact product
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/:contact/products/:product');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request DELETE 'https://api.kwiga.com/contacts/:contact/products/:product' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// Delete contact product
const url = 'https://api.kwiga.com/contacts/:contact/products/:product';
const options = {
method: 'DELETE',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Delete contact product
import requests
url = 'https://api.kwiga.com/contacts/:contact/products/:product'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.delete(url, headers=headers)
result = response.json()
{
"method": "DELETE",
"url": "https://api.kwiga.com/contacts/:contact/products/:product",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Приклад відповіді:
{
"success": true
}
DELETE https://api.kwiga.com/contacts/:contact/products/:product
Видаляє підписки контакту по заданому продукту. Замовлення стають кастомними без доступу до видалених продуктів.
Структура відповіді
Видалити продукти у контакта (масово)
Приклад запиту:
<?php
// Delete contact products in bulk
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
'json' => [
'email' => 'user@example.com',
'product_id' => 299,
'offers' => [421],
],
];
$response = $client->request('DELETE', '/contacts/products', $options);
$result = json_decode($response->getBody());
?>
<?php
// Delete contact products in bulk
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/products');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
$data = [
'email' => 'user@example.com',
'product_id' => 299,
'offers' => [421],
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request DELETE 'https://api.kwiga.com/contacts/products' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>' \
--data-raw '{"email":"user@example.com","product_id":299,"offers":[421]}'
// Delete contact products in bulk
const url = 'https://api.kwiga.com/contacts/products';
const options = {
method: 'DELETE',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
body: JSON.stringify({
'email': 'user@example.com',
'product_id': 299,
'offers': [421]
})
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Delete contact products in bulk
import requests
url = 'https://api.kwiga.com/contacts/products'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
data = {
'email': 'user@example.com',
'product_id': 299,
'offers': [421],
}
response = requests.delete(url, headers=headers, json=data)
result = response.json()
{
"method": "DELETE",
"url": "https://api.kwiga.com/contacts/products",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"email": "user@example.com",
"product_id": 299,
"offers": [
421
]
}
}
Приклад відповіді:
{
"data": {
"affected_subscriptions": [
2309,
2661
],
"affected_orders": [
1578,
1784
],
"affected_by_offers": {
"421": {
"affected_subscriptions": [
2309,
2661
],
"affected_orders": [
1578,
1784
]
}
},
"affected_by_products": []
},
"contact_id": 125
}
DELETE https://api.kwiga.com/contacts/products
Видаляє підписки за заданими умовами, а замовлення стають кастомними без доступу до видалених продуктів. Можна комбінувати параметри product_id та offers для видалення частини продуктів по певному офферу.
Parameters
Структура відповіді
Заморозити підписку контакту
Приклад запиту:
<?php
// Freeze the subscription for 30 days
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
'json' => [
'count_frozen_days' => 30,
],
];
$response = $client->request('POST', '/contacts/:contact/products/:product/freeze', $options);
$result = json_decode($response->getBody());
?>
<?php
// Freeze the subscription for 30 days
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/:contact/products/:product/freeze');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$data = [
'count_frozen_days' => 30,
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request POST 'https://api.kwiga.com/contacts/:contact/products/:product/freeze' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>' \
--data-raw '{"count_frozen_days":30}'
// Freeze the subscription for 30 days
const url = 'https://api.kwiga.com/contacts/:contact/products/:product/freeze';
const options = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
body: JSON.stringify({
'count_frozen_days': 30
})
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Freeze the subscription for 30 days
import requests
url = 'https://api.kwiga.com/contacts/:contact/products/:product/freeze'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
data = {
'count_frozen_days': 30,
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
{
"method": "POST",
"url": "https://api.kwiga.com/contacts/:contact/products/:product/freeze",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"count_frozen_days": 30
}
}
Приклад відповіді:
{
"data": {
"id": 299,
"productable_id": 142,
"productable_type": "course",
"title": "JS Foundations",
"image_url": "https://cdn.kwiga.com/preview.jpg",
"url": "https://kwiga.com/courses/js-foundations",
"is_published": true,
"aggregated_subscription": {
"is_active": false,
"is_paid": true,
"start_at": "2026-06-05T00:00:00.000000Z",
"end_at": "2026-08-04T00:00:00.000000Z",
"offer_end_at": null,
"order_end_at": "2026-08-04T00:00:00.000000Z",
"frozen_at": "2026-05-20T10:00:00.000000Z",
"extended_at": null,
"count_available_days": 60,
"count_left_days": 60,
"state": {
"id": 4,
"name": "Frozen",
"title": "Frozen"
}
},
"subscriptions": [
{
"id": 4775,
"creator_id": 24457,
"user_id": 24457,
"product_id": 299,
"order_id": 2710,
"offer_id": 757,
"is_active": false,
"start_at": "2026-06-05T00:00:00.000000Z",
"order_end_at": "2026-08-04T00:00:00.000000Z",
"end_at": "2026-08-04T00:00:00.000000Z",
"frozen_at": "2026-05-20T10:00:00.000000Z",
"extended_at": null,
"paid_at": "2026-05-05T15:09:04.000000Z",
"created_at": "2026-05-05T15:09:04.000000Z",
"updated_at": "2026-05-06T12:42:11.000000Z"
}
]
}
}
POST https://api.kwiga.com/contacts/:contact/products/:product/freeze
Заморожує всі активні підписки контакту на цьому продукті на count_frozen_days календарних днів. Заморозка зсуває start_at / end_at / order_end_at уперед, робить підписку неактивною і повідомляє учня. При розморожуванні (ручному або автоматичному після закінчення терміну) start_at повертається назад на основі даних замовлення учня, а не просто відкочується на ту ж дельту.
URL Parameters
Структура відповіді
Розморозити підписку контакту
Приклад запиту:
<?php
// Unfreeze the subscription (no body)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('POST', '/contacts/:contact/products/:product/unfreeze', $options);
$result = json_decode($response->getBody());
?>
<?php
// Unfreeze the subscription (no body)
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/:contact/products/:product/unfreeze');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$data = [
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request POST 'https://api.kwiga.com/contacts/:contact/products/:product/unfreeze' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// Unfreeze the subscription (no body)
const url = 'https://api.kwiga.com/contacts/:contact/products/:product/unfreeze';
const options = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Unfreeze the subscription (no body)
import requests
url = 'https://api.kwiga.com/contacts/:contact/products/:product/unfreeze'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.post(url, headers=headers)
result = response.json()
{
"method": "POST",
"url": "https://api.kwiga.com/contacts/:contact/products/:product/unfreeze",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Приклад відповіді:
{
"data": {
"id": 299,
"productable_id": 142,
"productable_type": "course",
"title": "JS Foundations",
"image_url": "https://cdn.kwiga.com/preview.jpg",
"url": "https://kwiga.com/courses/js-foundations",
"is_published": true,
"aggregated_subscription": {
"is_active": false,
"is_paid": true,
"start_at": "2026-06-05T00:00:00.000000Z",
"end_at": "2026-08-04T00:00:00.000000Z",
"offer_end_at": null,
"order_end_at": "2026-08-04T00:00:00.000000Z",
"frozen_at": "2026-05-20T10:00:00.000000Z",
"extended_at": null,
"count_available_days": 60,
"count_left_days": 60,
"state": {
"id": 4,
"name": "Frozen",
"title": "Frozen"
}
},
"subscriptions": [
{
"id": 4775,
"creator_id": 24457,
"user_id": 24457,
"product_id": 299,
"order_id": 2710,
"offer_id": 757,
"is_active": false,
"start_at": "2026-06-05T00:00:00.000000Z",
"order_end_at": "2026-08-04T00:00:00.000000Z",
"end_at": "2026-08-04T00:00:00.000000Z",
"frozen_at": "2026-05-20T10:00:00.000000Z",
"extended_at": null,
"paid_at": "2026-05-05T15:09:04.000000Z",
"created_at": "2026-05-05T15:09:04.000000Z",
"updated_at": "2026-05-06T12:42:11.000000Z"
}
]
}
}
POST https://api.kwiga.com/contacts/:contact/products/:product/unfreeze
Розморожує всі заморожені підписки контакту на цьому продукті. Відновлює start_at, перераховує end_at / order_end_at (віднімає невикористаний залишок заморозки), активує доступ, якщо він не закінчився, і повідомляє учня. Тіло порожнє.
Структура відповіді
Продовжити підписку контакту
Приклад запиту:
<?php
// Extend access by 14 days
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
'json' => [
'count_extend_days' => 14,
],
];
$response = $client->request('POST', '/contacts/:contact/products/:product/extend', $options);
$result = json_decode($response->getBody());
?>
<?php
// Extend access by 14 days
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/:contact/products/:product/extend');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$data = [
'count_extend_days' => 14,
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request POST 'https://api.kwiga.com/contacts/:contact/products/:product/extend' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>' \
--data-raw '{"count_extend_days":14}'
// Extend access by 14 days
const url = 'https://api.kwiga.com/contacts/:contact/products/:product/extend';
const options = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
body: JSON.stringify({
'count_extend_days': 14
})
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Extend access by 14 days
import requests
url = 'https://api.kwiga.com/contacts/:contact/products/:product/extend'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
data = {
'count_extend_days': 14,
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
{
"method": "POST",
"url": "https://api.kwiga.com/contacts/:contact/products/:product/extend",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"count_extend_days": 14
}
}
Приклад відповіді:
{
"data": {
"id": 299,
"productable_id": 142,
"productable_type": "course",
"title": "JS Foundations",
"image_url": "https://cdn.kwiga.com/preview.jpg",
"url": "https://kwiga.com/courses/js-foundations",
"is_published": true,
"aggregated_subscription": {
"is_active": false,
"is_paid": true,
"start_at": "2026-06-05T00:00:00.000000Z",
"end_at": "2026-08-04T00:00:00.000000Z",
"offer_end_at": null,
"order_end_at": "2026-08-04T00:00:00.000000Z",
"frozen_at": "2026-05-20T10:00:00.000000Z",
"extended_at": null,
"count_available_days": 60,
"count_left_days": 60,
"state": {
"id": 4,
"name": "Frozen",
"title": "Frozen"
}
},
"subscriptions": [
{
"id": 4775,
"creator_id": 24457,
"user_id": 24457,
"product_id": 299,
"order_id": 2710,
"offer_id": 757,
"is_active": false,
"start_at": "2026-06-05T00:00:00.000000Z",
"order_end_at": "2026-08-04T00:00:00.000000Z",
"end_at": "2026-08-04T00:00:00.000000Z",
"frozen_at": "2026-05-20T10:00:00.000000Z",
"extended_at": null,
"paid_at": "2026-05-05T15:09:04.000000Z",
"created_at": "2026-05-05T15:09:04.000000Z",
"updated_at": "2026-05-06T12:42:11.000000Z"
}
]
}
}
POST https://api.kwiga.com/contacts/:contact/products/:product/extend
Додає count_extend_days календарних днів до end_at / order_end_at усіх підписок контакту на цьому продукті. Той же ендпоінт використовується CRM-автоматизаціями для реактивації прострочених підписок.
URL Parameters
Структура відповіді
Змінити дату закінчення підписки
Приклад запиту:
<?php
// Set the subscription end to the given date in the chosen timezone
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
'json' => [
'end_at' => '2027-01-01 23:59:59',
'timezone_id' => 1,
],
];
$response = $client->request('PUT', '/contacts/:contact/products/:product/end-date', $options);
$result = json_decode($response->getBody());
?>
<?php
// Set the subscription end to the given date in the chosen timezone
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/:contact/products/:product/end-date');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
$data = [
'end_at' => '2027-01-01 23:59:59',
'timezone_id' => 1,
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request PUT 'https://api.kwiga.com/contacts/:contact/products/:product/end-date' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>' \
--data-raw '{"end_at":"2027-01-01 23:59:59","timezone_id":1}'
// Set the subscription end to the given date in the chosen timezone
const url = 'https://api.kwiga.com/contacts/:contact/products/:product/end-date';
const options = {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
body: JSON.stringify({
'end_at': '2027-01-01 23:59:59',
'timezone_id': 1
})
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Set the subscription end to the given date in the chosen timezone
import requests
url = 'https://api.kwiga.com/contacts/:contact/products/:product/end-date'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
data = {
'end_at': '2027-01-01 23:59:59',
'timezone_id': 1,
}
response = requests.put(url, headers=headers, json=data)
result = response.json()
{
"method": "PUT",
"url": "https://api.kwiga.com/contacts/:contact/products/:product/end-date",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"end_at": "2027-01-01 23:59:59",
"timezone_id": 1
}
}
Приклад відповіді:
{
"data": {
"id": 299,
"productable_id": 142,
"productable_type": "course",
"title": "JS Foundations",
"image_url": "https://cdn.kwiga.com/preview.jpg",
"url": "https://kwiga.com/courses/js-foundations",
"is_published": true,
"aggregated_subscription": {
"is_active": false,
"is_paid": true,
"start_at": "2026-06-05T00:00:00.000000Z",
"end_at": "2026-08-04T00:00:00.000000Z",
"offer_end_at": null,
"order_end_at": "2026-08-04T00:00:00.000000Z",
"frozen_at": "2026-05-20T10:00:00.000000Z",
"extended_at": null,
"count_available_days": 60,
"count_left_days": 60,
"state": {
"id": 4,
"name": "Frozen",
"title": "Frozen"
}
},
"subscriptions": [
{
"id": 4775,
"creator_id": 24457,
"user_id": 24457,
"product_id": 299,
"order_id": 2710,
"offer_id": 757,
"is_active": false,
"start_at": "2026-06-05T00:00:00.000000Z",
"order_end_at": "2026-08-04T00:00:00.000000Z",
"end_at": "2026-08-04T00:00:00.000000Z",
"frozen_at": "2026-05-20T10:00:00.000000Z",
"extended_at": null,
"paid_at": "2026-05-05T15:09:04.000000Z",
"created_at": "2026-05-05T15:09:04.000000Z",
"updated_at": "2026-05-06T12:42:11.000000Z"
}
]
}
}
PUT https://api.kwiga.com/contacts/:contact/products/:product/end-date
Перезаписує end_at (і order_end_at, якщо вона є) явною датою. Дата інтерпретується у таймзоні timezone_id (див. ендпоінт списку таймзон); якщо timezone_id не вказано, end_at трактується як UTC.
URL Parameters
timezone_id.
end_at трактується як UTC.
Структура відповіді
Бали (нагороди)
Журнал балів контакту
Приклад запиту:
<?php
// List rewards (default ordering)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/contacts/:contact/rewards', $options);
$result = json_decode($response->getBody());
?>
# ---
# Filtered example
# ---
<?php
// Only accruals from quiz-passed and manual reasons, scoped to two products
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/contacts/:contact/rewards?filters[accrual_type]=accrued&filters[reason_types]=1,6&filters[product_ids]=10,11&per_page=50', $options);
$result = json_decode($response->getBody());
?>
<?php
// List rewards (default ordering)
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/:contact/rewards');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
# ---
# Filtered example
# ---
<?php
// Only accruals from quiz-passed and manual reasons, scoped to two products
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/:contact/rewards?filters[accrual_type]=accrued&filters[reason_types]=1,6&filters[product_ids]=10,11&per_page=50');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request GET 'https://api.kwiga.com/contacts/:contact/rewards' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
# ---
# Filtered example
# ---
curl --location --request GET 'https://api.kwiga.com/contacts/:contact/rewards?filters[accrual_type]=accrued&filters[reason_types]=1,6&filters[product_ids]=10,11&per_page=50' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// List rewards (default ordering)
const url = 'https://api.kwiga.com/contacts/:contact/rewards';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# ---
# Filtered example
# ---
// Only accruals from quiz-passed and manual reasons, scoped to two products
const url = 'https://api.kwiga.com/contacts/:contact/rewards?filters[accrual_type]=accrued&filters[reason_types]=1,6&filters[product_ids]=10,11&per_page=50';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# List rewards (default ordering)
import requests
url = 'https://api.kwiga.com/contacts/:contact/rewards'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
# ---
# Filtered example
# ---
# Only accruals from quiz-passed and manual reasons, scoped to two products
import requests
url = 'https://api.kwiga.com/contacts/:contact/rewards?filters[accrual_type]=accrued&filters[reason_types]=1,6&filters[product_ids]=10,11&per_page=50'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
{
"method": "GET",
"url": "https://api.kwiga.com/contacts/:contact/rewards",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
# ---
# Filtered example
# ---
{
"method": "GET",
"url": "https://api.kwiga.com/contacts/:contact/rewards?filters[accrual_type]=accrued&filters[reason_types]=1,6&filters[product_ids]=10,11&per_page=50",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Приклад відповіді:
{
"data": [
{
"id": 9821,
"points": 50,
"accrual_type": {
"id": "accrued",
"slug": "Plus",
"title": "Accrued"
},
"reason_type": {
"id": 6,
"slug": "Manual",
"title": "Manual"
},
"event": null,
"event_name": null,
"eventable_type": null,
"eventable_id": null,
"event_comment": null,
"manual_comment": "Bonus for active chat participation",
"is_visible_to_student": true,
"message": "Manual points accrual: Bonus for active chat participation",
"product": null,
"creator": {
"id": 17,
"name": "Alice Curator",
"email": "alice@kwiga.com"
},
"created_at": "2026-05-24T11:14:51.000000Z"
},
{
"id": 9820,
"points": 25,
"accrual_type": {
"id": "accrued",
"slug": "Plus",
"title": "Accrued"
},
"reason_type": {
"id": 1,
"slug": "QuizPassed",
"title": "Quiz passed"
},
"event": "quiz.passed",
"event_name": "Quiz passed",
"eventable_type": "quiz_attempt",
"eventable_id": 4821,
"event_comment": null,
"manual_comment": null,
"is_visible_to_student": null,
"message": "Quiz Module 3 final test in lesson Closures & scope -> Attempt",
"product": {
"id": 431,
"productable_type": "course",
"productable_id": 226,
"name": "JS Foundations",
"url": "https://lm4.kwiga.com/courses/js-foundations"
},
"creator": null,
"created_at": "2026-05-23T11:14:51.000000Z"
},
{
"id": 9810,
"points": -30,
"accrual_type": {
"id": "deducted",
"slug": "Minus",
"title": "Deducted"
},
"reason_type": {
"id": 6,
"slug": "Manual",
"title": "Manual"
},
"event": null,
"event_name": null,
"eventable_type": null,
"eventable_id": null,
"event_comment": null,
"manual_comment": null,
"is_visible_to_student": null,
"message": "Manual points accrual",
"product": null,
"creator": {
"id": 17,
"name": "Alice Curator",
"email": "alice@kwiga.com"
},
"created_at": "2026-05-22T09:00:00.000000Z"
}
],
"links": {
"first": "https://api.kwiga.com/contacts/142/rewards?page=1",
"last": "https://api.kwiga.com/contacts/142/rewards?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "https://api.kwiga.com/contacts/142/rewards",
"per_page": 15,
"to": 3,
"total": 3
},
"sum_points": 45,
"sum_accrued_points": 75,
"sum_deducted_points": -30
}
GET https://api.kwiga.com/contacts/:contact/rewards
Повертає журнал нарахувань і списань балів контакту — за квізами, замовленнями, подарунками, автоматизаціями і ручними діями кураторів. На верхньому рівні відповіді також повертаються суми sum_points, sum_accrued_points, sum_deducted_points за поточним фільтром.
URL Parameters
151Структура відповіді
Ручне нарахування/списання балів контакту Ідемпотентний
Приклад запиту:
<?php
// Accrue 50 points for finishing a milestone, unbound from any product
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
'json' => [
'points' => 50,
],
];
$response = $client->request('POST', '/contacts/:contact/rewards', $options);
$result = json_decode($response->getBody());
?>
# ---
# Accrue_with_product example
# ---
<?php
// Accrue 100 points scoped to product id 10
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
'json' => [
'points' => 100,
'product_id' => 10,
],
];
$response = $client->request('POST', '/contacts/:contact/rewards', $options);
$result = json_decode($response->getBody());
?>
# ---
# With_comment example
# ---
<?php
// Accrue 50 points with a curator comment that the student also sees in their journal
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
'json' => [
'points' => 50,
'comment' => 'Bonus for active chat participation',
'is_visible_to_student' => true,
],
];
$response = $client->request('POST', '/contacts/:contact/rewards', $options);
$result = json_decode($response->getBody());
?>
# ---
# Idempotent_accrual example
# ---
<?php
// Safely retry the same accrual — passing Idempotency-Key collapses replays to a single FlowReward
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
'Idempotency-Key' => 'reward-for-quiz-attempt-4821',
],
'json' => [
'points' => 25,
],
];
$response = $client->request('POST', '/contacts/:contact/rewards', $options);
$result = json_decode($response->getBody());
?>
# ---
# Deduct example
# ---
<?php
// Deduct 30 points
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
'json' => [
'points' => -30,
],
];
$response = $client->request('POST', '/contacts/:contact/rewards', $options);
$result = json_decode($response->getBody());
?>
<?php
// Accrue 50 points for finishing a milestone, unbound from any product
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/:contact/rewards');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$data = [
'points' => 50,
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
# ---
# Accrue_with_product example
# ---
<?php
// Accrue 100 points scoped to product id 10
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/:contact/rewards');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$data = [
'points' => 100,
'product_id' => 10,
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
# ---
# With_comment example
# ---
<?php
// Accrue 50 points with a curator comment that the student also sees in their journal
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/:contact/rewards');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$data = [
'points' => 50,
'comment' => 'Bonus for active chat participation',
'is_visible_to_student' => true,
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
# ---
# Idempotent_accrual example
# ---
<?php
// Safely retry the same accrual — passing Idempotency-Key collapses replays to a single FlowReward
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
'Idempotency-Key: reward-for-quiz-attempt-4821',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/:contact/rewards');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$data = [
'points' => 25,
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
# ---
# Deduct example
# ---
<?php
// Deduct 30 points
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/contacts/:contact/rewards');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$data = [
'points' => -30,
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request POST 'https://api.kwiga.com/contacts/:contact/rewards' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>' \
--data-raw '{"points":50}'
# ---
# Accrue_with_product example
# ---
curl --location --request POST 'https://api.kwiga.com/contacts/:contact/rewards' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>' \
--data-raw '{"points":100,"product_id":10}'
# ---
# With_comment example
# ---
curl --location --request POST 'https://api.kwiga.com/contacts/:contact/rewards' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>' \
--data-raw '{"points":50,"comment":"Bonus for active chat participation","is_visible_to_student":true}'
# ---
# Idempotent_accrual example
# ---
curl --location --request POST 'https://api.kwiga.com/contacts/:contact/rewards' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>' \
--header 'Idempotency-Key: reward-for-quiz-attempt-4821' \
--data-raw '{"points":25}'
# ---
# Deduct example
# ---
curl --location --request POST 'https://api.kwiga.com/contacts/:contact/rewards' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>' \
--data-raw '{"points":-30}'
// Accrue 50 points for finishing a milestone, unbound from any product
const url = 'https://api.kwiga.com/contacts/:contact/rewards';
const options = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
body: JSON.stringify({
'points': 50
})
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# ---
# Accrue_with_product example
# ---
// Accrue 100 points scoped to product id 10
const url = 'https://api.kwiga.com/contacts/:contact/rewards';
const options = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
body: JSON.stringify({
'points': 100,
'product_id': 10
})
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# ---
# With_comment example
# ---
// Accrue 50 points with a curator comment that the student also sees in their journal
const url = 'https://api.kwiga.com/contacts/:contact/rewards';
const options = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
body: JSON.stringify({
'points': 50,
'comment': 'Bonus for active chat participation',
'is_visible_to_student': true
})
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# ---
# Idempotent_accrual example
# ---
// Safely retry the same accrual — passing Idempotency-Key collapses replays to a single FlowReward
const url = 'https://api.kwiga.com/contacts/:contact/rewards';
const options = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
'Idempotency-Key': 'reward-for-quiz-attempt-4821',
},
body: JSON.stringify({
'points': 25
})
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# ---
# Deduct example
# ---
// Deduct 30 points
const url = 'https://api.kwiga.com/contacts/:contact/rewards';
const options = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
body: JSON.stringify({
'points': -30
})
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Accrue 50 points for finishing a milestone, unbound from any product
import requests
url = 'https://api.kwiga.com/contacts/:contact/rewards'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
data = {
'points': 50,
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
# ---
# Accrue_with_product example
# ---
# Accrue 100 points scoped to product id 10
import requests
url = 'https://api.kwiga.com/contacts/:contact/rewards'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
data = {
'points': 100,
'product_id': 10,
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
# ---
# With_comment example
# ---
# Accrue 50 points with a curator comment that the student also sees in their journal
import requests
url = 'https://api.kwiga.com/contacts/:contact/rewards'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
data = {
'points': 50,
'comment': 'Bonus for active chat participation',
'is_visible_to_student': true,
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
# ---
# Idempotent_accrual example
# ---
# Safely retry the same accrual — passing Idempotency-Key collapses replays to a single FlowReward
import requests
url = 'https://api.kwiga.com/contacts/:contact/rewards'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
'Idempotency-Key': 'reward-for-quiz-attempt-4821',
}
data = {
'points': 25,
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
# ---
# Deduct example
# ---
# Deduct 30 points
import requests
url = 'https://api.kwiga.com/contacts/:contact/rewards'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
data = {
'points': -30,
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
{
"method": "POST",
"url": "https://api.kwiga.com/contacts/:contact/rewards",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"points": 50
}
}
# ---
# Accrue_with_product example
# ---
{
"method": "POST",
"url": "https://api.kwiga.com/contacts/:contact/rewards",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"points": 100,
"product_id": 10
}
}
# ---
# With_comment example
# ---
{
"method": "POST",
"url": "https://api.kwiga.com/contacts/:contact/rewards",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"points": 50,
"comment": "Bonus for active chat participation",
"is_visible_to_student": true
}
}
# ---
# Idempotent_accrual example
# ---
{
"method": "POST",
"url": "https://api.kwiga.com/contacts/:contact/rewards",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Idempotency-Key": "reward-for-quiz-attempt-4821",
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"points": 25
}
}
# ---
# Deduct example
# ---
{
"method": "POST",
"url": "https://api.kwiga.com/contacts/:contact/rewards",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"points": -30
}
}
Приклад відповіді:
{
"data": {
"id": 9822,
"points": 50,
"accrual_type": {
"id": "accrued",
"slug": "Plus",
"title": "Accrued"
},
"reason_type": {
"id": 6,
"slug": "Manual",
"title": "Manual"
},
"event": null,
"event_name": null,
"eventable_type": null,
"eventable_id": null,
"event_comment": null,
"manual_comment": "Bonus for active chat participation",
"is_visible_to_student": true,
"message": "Manual points accrual: Bonus for active chat participation",
"product": null,
"creator": {
"id": 17,
"name": "Alice Curator",
"email": "alice@kwiga.com"
},
"created_at": "2026-05-25T14:30:00.000000Z"
}
}
POST https://api.kwiga.com/contacts/:contact/rewards
Додає ручний запис у журнал балів контакту. Додатнє points — нарахування, від'ємне — списання. Опціональний product_id прив'язує запис до конкретного продукту; інакше — «кабінет-рівневе». Reason type завжди Manual; куратором фіксується поточний API-користувач.
URL Parameters
message у відповіді. Учень побачить коментар у своєму журналі балів лише якщо is_visible_to_student=true.
falseСтруктура відповіді
Продукти
Список продуктів кабінету
Приклад запиту:
<?php
// Get products list
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/products', $options);
$result = json_decode($response->getBody());
?>
# ---
# Paginated example
# ---
<?php
// Get products list with pagination and sorting
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/products?per_page=20&page=1&sort_by=asc', $options);
$result = json_decode($response->getBody());
?>
<?php
// Get products list
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/products');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
# ---
# Paginated example
# ---
<?php
// Get products list with pagination and sorting
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/products?per_page=20&page=1&sort_by=asc');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request GET 'https://api.kwiga.com/products' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
# ---
# Paginated example
# ---
curl --location --request GET 'https://api.kwiga.com/products?per_page=20&page=1&sort_by=asc' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// Get products list
const url = 'https://api.kwiga.com/products';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# ---
# Paginated example
# ---
// Get products list with pagination and sorting
const url = 'https://api.kwiga.com/products?per_page=20&page=1&sort_by=asc';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Get products list
import requests
url = 'https://api.kwiga.com/products'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
# ---
# Paginated example
# ---
# Get products list with pagination and sorting
import requests
url = 'https://api.kwiga.com/products?per_page=20&page=1&sort_by=asc'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
{
"method": "GET",
"url": "https://api.kwiga.com/products",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
# ---
# Paginated example
# ---
{
"method": "GET",
"url": "https://api.kwiga.com/products?per_page=20&page=1&sort_by=asc",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Приклад відповіді:
{
"data": [
{
"id": 299,
"productable_id": 142,
"productable_type": "course",
"title": "Sample Course Title",
"url": "http://test.local/courses/test-slug"
}
],
"links": {
"first": "https://api.kwiga.com/products?page=1",
"last": "https://api.kwiga.com/products?page=5",
"prev": null,
"next": "https://api.kwiga.com/products?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 5,
"path": "https://api.kwiga.com/products",
"per_page": 15,
"to": 15,
"total": 75
}
}
GET https://api.kwiga.com/products
Список продуктів кабінету. Є пагінація, за замовчуванням 15.
URL Parameters
asc, descDefault: desc151Структура відповіді
Курси
Список курсів кабінету
Приклад запиту:
<?php
// Get courses list
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/courses', $options);
$result = json_decode($response->getBody());
?>
# ---
# With_params example
# ---
<?php
// Get courses list with pagination and includes
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/courses?with[]=offers&with[]=description&with[]=program&per_page=15&page=1', $options);
$result = json_decode($response->getBody());
?>
<?php
// Get courses list
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/courses');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
# ---
# With_params example
# ---
<?php
// Get courses list with pagination and includes
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/courses?with[]=offers&with[]=description&with[]=program&per_page=15&page=1');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request GET 'https://api.kwiga.com/courses' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
# ---
# With_params example
# ---
curl --location --request GET 'https://api.kwiga.com/courses?with[]=offers&with[]=description&with[]=program&per_page=15&page=1' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// Get courses list
const url = 'https://api.kwiga.com/courses';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# ---
# With_params example
# ---
// Get courses list with pagination and includes
const url = 'https://api.kwiga.com/courses?with[]=offers&with[]=description&with[]=program&per_page=15&page=1';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Get courses list
import requests
url = 'https://api.kwiga.com/courses'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
# ---
# With_params example
# ---
# Get courses list with pagination and includes
import requests
url = 'https://api.kwiga.com/courses?with[]=offers&with[]=description&with[]=program&per_page=15&page=1'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
{
"method": "GET",
"url": "https://api.kwiga.com/courses",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
# ---
# With_params example
# ---
{
"method": "GET",
"url": "https://api.kwiga.com/courses?with[]=offers&with[]=description&with[]=program&per_page=15&page=1",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Приклад відповіді:
{
"data": [
{
"id": 226,
"product_id": 431,
"type": {
"id": 1,
"name": "Course",
"type": "course"
},
"title": "Test черновик квизов",
"slug": "test-chernovik-kvizov",
"preview": {
"id": 3140,
"uuid": "bdfe1347-574f-4829-a745-09ba2176cc2a",
"name": "image_13.jpeg",
"original_name": "image_13.jpeg",
"url": "https://cdn57098163.ahacdn.me/local/cabinet-1/rcIJuNkWmpCQ/image_13.jpeg",
"thumbnails": {
"xs": "https://cdn57098163.ahacdn.me/local/cabinet-1/rcIJuNkWmpCQ/image_13_thumb_150.jpeg",
"small": "https://cdn57098163.ahacdn.me/local/cabinet-1/rcIJuNkWmpCQ/image_13_thumb_500.jpeg",
"medium": "https://cdn57098163.ahacdn.me/local/cabinet-1/rcIJuNkWmpCQ/image_13.jpeg",
"large": "https://cdn57098163.ahacdn.me/local/cabinet-1/rcIJuNkWmpCQ/image_13.jpeg",
"default": "https://cdn57098163.ahacdn.me/local/cabinet-1/rcIJuNkWmpCQ/image_13.jpeg"
},
"extension": "jpeg",
"type_id": 2,
"mime_type": "image/jpeg"
},
"url": "http://test.local/courses/test-chernovik-kvizov",
"status": {
"id": 3,
"name": "Published"
}
}
],
"links": {
"first": "http://api.kwiga.local/courses?page=1",
"last": "http://api.kwiga.local/courses?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"links": [
{
"url": null,
"label": "« Previous",
"active": false
},
{
"url": "http://api.kwiga.local/courses?page=1",
"label": "1",
"active": true
},
{
"url": null,
"label": "Next »",
"active": false
}
],
"path": "http://api.kwiga.local/courses",
"per_page": 15,
"to": 1,
"total": 1
}
}
GET https://api.kwiga.com/courses
Список курсів кабінету. Є пагінація, за замовчуванням 15 (max: 15).
URL Parameters
offers, description, programasc, descDefault: desc151Структура відповіді
Список учасників курсу
Приклад запиту:
<?php
// Get course users
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/courses/:course/users', $options);
$result = json_decode($response->getBody());
?>
# ---
# Filtered example
# ---
<?php
// Get course users with filters
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/courses/:course/users?progress_general_from=50&progress_general_to=100&per_page=20', $options);
$result = json_decode($response->getBody());
?>
<?php
// Get course users
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/courses/:course/users');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
# ---
# Filtered example
# ---
<?php
// Get course users with filters
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/courses/:course/users?progress_general_from=50&progress_general_to=100&per_page=20');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request GET 'https://api.kwiga.com/courses/:course/users' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
# ---
# Filtered example
# ---
curl --location --request GET 'https://api.kwiga.com/courses/:course/users?progress_general_from=50&progress_general_to=100&per_page=20' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// Get course users
const url = 'https://api.kwiga.com/courses/:course/users';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# ---
# Filtered example
# ---
// Get course users with filters
const url = 'https://api.kwiga.com/courses/:course/users?progress_general_from=50&progress_general_to=100&per_page=20';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Get course users
import requests
url = 'https://api.kwiga.com/courses/:course/users'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
# ---
# Filtered example
# ---
# Get course users with filters
import requests
url = 'https://api.kwiga.com/courses/:course/users?progress_general_from=50&progress_general_to=100&per_page=20'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
{
"method": "GET",
"url": "https://api.kwiga.com/courses/:course/users",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
# ---
# Filtered example
# ---
{
"method": "GET",
"url": "https://api.kwiga.com/courses/:course/users?progress_general_from=50&progress_general_to=100&per_page=20",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Приклад відповіді:
{
"data": [
{
"user": {
"id": 3,
"name": "Admin Кабинет",
"email": "test@test.com"
},
"contact": {
"id": 1,
"user_id": 3,
"email": "test@test.com",
"first_name": "test",
"last_name": "admin cabinet",
"phone": "979",
"created_at": "2023-05-26T09:47:20.000000Z",
"last_activity_at": null
},
"course_points": 0,
"course_progress": {
"course_id": 20,
"course_url": "http://test.local/courses/Pm8CEofJ",
"title": "Dripping",
"lessons_count": 9,
"lessons_count_viewed": 0,
"lessons_viewed_percentage": 0,
"lessons_count_completed": 0,
"lessons_completion_percentage": 0,
"quizzes_count": 0,
"quizzes_count_completed": 0,
"quizzes_completion_percentage": 0,
"scores_max": 0,
"quizzes_scores": 0,
"product_scores": 0,
"scores": 0,
"is_completed": false,
"completed_at": null,
"current_lesson": {
"id": 48,
"course_id": 20,
"type_id": 1,
"status_id": 4,
"number": 6,
"title": "2",
"slug": "2",
"url": "http://test.local/courses/Pm8CEofJ/2",
"quizzes": [],
"module": {
"id": 7,
"course_id": 20,
"number": 1,
"title": "Module title"
}
},
"next_lesson": {
"id": 46,
"course_id": 20,
"type_id": 1,
"status_id": 4,
"number": 1,
"title": "3",
"slug": "3",
"url": "http://test.local/courses/Pm8CEofJ/3",
"module": {
"id": 7,
"course_id": 20,
"number": 1,
"title": "Module title"
}
},
"last_activity_at": null,
"is_checkpoints_skipped": false,
"checkpoints": [],
"is_current_dripping_date_skipped": false,
"is_next_dripping_date_skipped": false,
"current_dripping_date": null,
"next_dripping_date": null
},
"lessons_available_count": 9,
"is_full_access": true,
"subscription": {
"is_active": true,
"is_paid": true,
"start_at": "2024-04-23T13:45:02.000000Z",
"end_at": null,
"offer_end_at": null,
"order_end_at": null,
"count_available_days": 661,
"count_left_days": null,
"state": {
"id": 2,
"name": "Open",
"title": "Open"
}
}
}
],
"links": {
"first": "http://api.kwiga.local/courses/20/users?page=1",
"last": "http://api.kwiga.local/courses/20/users?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"links": [
{
"url": null,
"label": "« Previous",
"active": false
},
{
"url": "http://api.kwiga.local/courses/20/users?page=1",
"label": "1",
"active": true
},
{
"url": null,
"label": "Next »",
"active": false
}
],
"path": "http://api.kwiga.local/courses/20/users",
"per_page": 15,
"to": 1,
"total": 1
}
}
GET https://api.kwiga.com/courses/:course/users
Виводить список учасників курсу та їх прогрес. Є пагінація, за замовчуванням 15 (max: 250). Замініть :course на id курсу, який можна взяти в адресному рядку редагування/управління курсу або в ендпоінті по списку курсів.
URL Parameters
emails / contact_ids / user_id / user_ids у єдиний фільтр аудиторії (union).
emails / contact_id / user_id / user_ids у єдиний фільтр аудиторії (union).
emails / contact_id / contact_ids / user_ids у єдиний фільтр аудиторії (union).
emails / contact_id / contact_ids / user_id у єдиний фільтр аудиторії (union).
contact_id / contact_ids / user_id / user_ids у єдиний фільтр аудиторії (union).
151Необов'язковий список розширень відповіді через кому. Кожен токен підключає одну секцію відповіді — клієнт платить лише за те, що попросив.
course_program— додає програму курсу на верхньому рівні відповіді у полеcourse_program(масив вузлів CourseProgram; у lesson-вузлів уchildrenідуть CourseProgramSection з прив'язаними квізами). Повертається один раз поряд зdata/links/meta, бо програма однакова для всіх учнів сторінки.lesson_progress— додає у кожен елементdata[]полеlesson_progress: масив об'єктів LessonProgress (по одному запису на урок, по якому в учня є прогрес).module_progress— додає у кожен елементdata[]полеmodule_progress: масив об'єктів ModuleProgress.quiz_progress— додає у кожен елементdata[]полеquiz_progress: масив об'єктів QuizProgress, по одному запису на пару(course_lesson_id, quiz_id)зі зведенням за останньою non-cancelled спробою учня.
Увага: один і той самий квіз може бути прив'язаний до кількох уроків одного курсу, тому quiz_progress адресується парою урок/квіз, а не одним quiz_id. Клієнт зшиває per-user прогрес з деревом за course_nodeble_id lesson/module-вузлів і за парою (lesson.course_nodeble_id, quizzes[i].id) для section-вузлів.
Структура відповіді
include contains course_program.Програма курсу, повертається на верхньому рівні коли `include` містить `course_program`. Форма полів та сама, що в існуючій схемі `CourseProgram`, у lesson-вузлів у `children` лежать `CourseProgramSection`. Однакова для всіх учнів сторінки, тому API повертає її один раз замість повторення в кожному ряду.
POST-аліас
POST https://api.kwiga.com/courses/:course/users/query
Функціональний аліас для GET-ендпоінта вище. Приймає ті самі параметри в тілі запиту замість query-string — стане в нагоді, коли список фільтрів завеликий для URL (або просто зручніше збирати JSON на клієнті). Body має пріоритет над query-string, форма відповіді ідентична.
Отримання детальної аналітики по уроках
На додачу до зведення прогресу по курсу ендпоінт може повернути
детальну розбивку прогресу по уроках. Розширення запитується
query-параметром include (повний список токенів і тип даних,
який кожен з них підключає, описаний у його описі вище, в URL
Parameters). Програма курсу повертається один раз на верхньому
рівні у полі course_program — вона однакова для всіх учнів
сторінки, тому розмір відповіді залишається пропорційним добутку
учнів на уроки/квізи, а не на розмір усього дерева.
Приклад відповіді з
?include=course_program,lesson_progress,module_progress,quiz_progress
{
"data": [
{
"user": {
"id": 3,
"name": "Admin Кабинет",
"email": "test@test.com"
},
"contact": {
"id": 1,
"user_id": 3,
"email": "test@test.com",
"first_name": "test",
"last_name": "admin cabinet",
"phone": "979",
"created_at": "2023-05-26T09:47:20.000000Z",
"last_activity_at": null
},
"course_points": 0,
"course_progress": {
"course_id": 20,
"title": "Dripping",
"lessons_count": 9,
"lessons_count_viewed": 2,
"lessons_viewed_percentage": 22,
"lessons_count_completed": 1,
"lessons_completion_percentage": 11,
"quizzes_count": 2,
"quizzes_count_completed": 1,
"quizzes_completion_percentage": 50,
"scores_max": 200,
"quizzes_scores": 80,
"is_completed": false,
"completed_at": null
},
"lessons_available_count": 9,
"is_full_access": true,
"lesson_progress": [
{
"lesson_id": 48,
"is_watched": true,
"is_completed": true,
"quizzing_status": {
"id": 4,
"slug": "Completed",
"title": "Completed"
},
"watching_start_at": "2026-05-20T11:20:00.000000Z",
"watching_end_at": "2026-05-20T11:30:00.000000Z",
"quizzing_start_at": "2026-05-20T11:30:00.000000Z",
"quizzing_end_at": "2026-05-20T11:34:00.000000Z",
"completed_at": "2026-05-20T11:35:00.000000Z",
"created_at": "2026-05-20T11:20:00.000000Z",
"updated_at": "2026-05-20T11:35:00.000000Z"
},
{
"lesson_id": 46,
"is_watched": true,
"is_completed": false,
"quizzing_status": {
"id": 3,
"slug": "InProgress",
"title": "In progress"
},
"watching_start_at": "2026-05-21T09:00:00.000000Z",
"watching_end_at": "2026-05-21T09:10:00.000000Z",
"quizzing_start_at": null,
"quizzing_end_at": null,
"completed_at": null,
"created_at": "2026-05-21T09:00:00.000000Z",
"updated_at": "2026-05-21T09:10:00.000000Z"
}
],
"module_progress": [
{
"module_id": 7,
"is_watched": true,
"is_completed": false,
"quizzing_status": {
"id": 3,
"slug": "InProgress",
"title": "In progress"
},
"watching_start_at": "2026-05-20T11:20:00.000000Z",
"watching_end_at": "2026-05-21T09:10:00.000000Z",
"quizzing_start_at": null,
"quizzing_end_at": null,
"completed_at": null,
"created_at": "2026-05-20T11:20:00.000000Z",
"updated_at": "2026-05-21T09:10:00.000000Z"
}
],
"quiz_progress": [
{
"course_lesson_id": 48,
"quiz_id": 101,
"status": {
"id": 1,
"slug": "Passed",
"title": "Passed"
},
"scores": 80,
"scores_max": 100,
"started_at": "2026-05-20T11:30:00.000000Z",
"finished_at": "2026-05-20T11:34:00.000000Z",
"checked_at": null,
"last_activity_at": "2026-05-20T11:34:00.000000Z",
"attempt_number": 2
}
]
}
],
"links": {
"first": "https://api.example.com/courses/20/users?page=1",
"last": "https://api.example.com/courses/20/users?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "https://api.example.com/courses/20/users",
"per_page": 15,
"to": 1,
"total": 1
},
"course_structure": [
{
"id": 12,
"course_nodeble_type": "course_module",
"course_nodeble_id": 7,
"parent_id": null,
"order": 1,
"course_nodeble": {
"id": 7,
"title": "Module title"
},
"children": [
{
"id": 34,
"course_nodeble_type": "course_lesson",
"course_nodeble_id": 48,
"parent_id": 12,
"order": 1,
"course_nodeble": {
"id": 48,
"title": "Lesson 1"
},
"children": [
{
"id": 201,
"course_nodeble_type": "info_section",
"course_nodeble_id": 201,
"parent_id": 34,
"order": 1,
"course_nodeble": {
"id": 201,
"name": "List of practice",
"slug": "list-of-practice"
},
"quizzes": [
{"id": 101, "name": "Module wrap-up quiz"}
],
"children": []
},
{
"id": 202,
"course_nodeble_type": "info_section",
"course_nodeble_id": 202,
"parent_id": 34,
"order": 2,
"course_nodeble": {
"id": 202,
"name": "Theory",
"slug": "theory"
},
"quizzes": [],
"children": []
}
]
},
{
"id": 35,
"course_nodeble_type": "course_lesson",
"course_nodeble_id": 46,
"parent_id": 12,
"order": 2,
"course_nodeble": {
"id": 46,
"title": "Lesson 2"
},
"children": [
{
"id": 203,
"course_nodeble_type": "info_section",
"course_nodeble_id": 203,
"parent_id": 35,
"order": 1,
"course_nodeble": {
"id": 203,
"name": "Intro",
"slug": "intro"
},
"quizzes": [],
"children": []
}
]
}
]
}
]
}
Зшивка прогресу з деревом
Ендпоінт повертає програму курсу один раз на верхньому рівні, а
масиви прогресу користувача — всередині кожного рядка data[].
Щоб накласти прогрес конкретного учня на дерево, зробіть так.
1. Побудуйте словники з його масивів прогресу для швидкого пошуку.
lesson_progress→ індексуйте заlesson_idmodule_progress→ індексуйте заmodule_idquiz_progress→ індексуйте за парою(course_lesson_id, quiz_id), бо один і той самий квіз може бути прив'язаний до кількох уроків
Про імена: записи прогресу використовують lesson_id/module_id/course_lesson_id,
а вузли програми — course_nodeble_id. Це одне й те саме значення,
просто в різних частинах відповіді — див. крок 2.
2. Обійдіть course_program і для кожного вузла візьміть потрібний запис.
У кожного вузла є course_nodeble_type + course_nodeble_id.
Використовуйте course_nodeble_id як ключ пошуку:
- вузол
course_module→module_progress[node.course_nodeble_id] - вузол
course_lesson→lesson_progress[node.course_nodeble_id] - вузол
info_section→ у секції власного прогресу немає. Пройдіться поnode.quizzesі для кожного квіза візьмітьquiz_progress[(parent_lesson.course_nodeble_id, quiz.id)], деparent_lesson— найближчий батьківський вузолcourse_lesson.
Якщо пошук нічого не повернув — в учня ще немає прогресу по цьому вузлу, відмалюйте порожній стан. Програма курсу однакова для всіх учнів сторінки, тому її безпечно побудувати один раз і перевикористати між рядками.
Спроби проходження квізів
Список спроб у кабінеті
Приклад запиту:
<?php
// List quiz attempts (defaults — newest first by status_updated_at)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/quiz-attempts', $options);
$result = json_decode($response->getBody());
?>
# ---
# Filtered example
# ---
<?php
// Filtered list — pending check & need rework, scoped to two products
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/quiz-attempts?filters[practice_statuses]=3,6&filters[product_ids]=10,11&sort_by=last_activity_at&sort_dir=desc&per_page=50', $options);
$result = json_decode($response->getBody());
?>
<?php
// List quiz attempts (defaults — newest first by status_updated_at)
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/quiz-attempts');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
# ---
# Filtered example
# ---
<?php
// Filtered list — pending check & need rework, scoped to two products
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/quiz-attempts?filters[practice_statuses]=3,6&filters[product_ids]=10,11&sort_by=last_activity_at&sort_dir=desc&per_page=50');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request GET 'https://api.kwiga.com/quiz-attempts' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
# ---
# Filtered example
# ---
curl --location --request GET 'https://api.kwiga.com/quiz-attempts?filters[practice_statuses]=3,6&filters[product_ids]=10,11&sort_by=last_activity_at&sort_dir=desc&per_page=50' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// List quiz attempts (defaults — newest first by status_updated_at)
const url = 'https://api.kwiga.com/quiz-attempts';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# ---
# Filtered example
# ---
// Filtered list — pending check & need rework, scoped to two products
const url = 'https://api.kwiga.com/quiz-attempts?filters[practice_statuses]=3,6&filters[product_ids]=10,11&sort_by=last_activity_at&sort_dir=desc&per_page=50';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# List quiz attempts (defaults — newest first by status_updated_at)
import requests
url = 'https://api.kwiga.com/quiz-attempts'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
# ---
# Filtered example
# ---
# Filtered list — pending check & need rework, scoped to two products
import requests
url = 'https://api.kwiga.com/quiz-attempts?filters[practice_statuses]=3,6&filters[product_ids]=10,11&sort_by=last_activity_at&sort_dir=desc&per_page=50'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
{
"method": "GET",
"url": "https://api.kwiga.com/quiz-attempts",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
# ---
# Filtered example
# ---
{
"method": "GET",
"url": "https://api.kwiga.com/quiz-attempts?filters[practice_statuses]=3,6&filters[product_ids]=10,11&sort_by=last_activity_at&sort_dir=desc&per_page=50",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Приклад відповіді:
{
"data": [
{
"id": 4821,
"root_id": 4810,
"previous_id": 4815,
"number_version": 3,
"user_id": 712,
"product_id": 431,
"quiz_id": 88,
"course_id": 226,
"course_lesson_id": 504,
"lesson_section": {
"id": 88,
"name": "Knowledge check",
"order": 3,
"url": "https://lm4.kwiga.com/courses/js-foundations/3/lessons/504",
"crm_url": "https://lm4.kwiga.com/expert/courses/js-foundations/3/lessons/504/sections/3"
},
"status": {
"id": 6,
"slug": "PendingCheck",
"title": "Pending review"
},
"scores": 12.5,
"scores_max": 15,
"count_questions": 10,
"count_questions_correct": 8,
"count_questions_incorrect": 2,
"is_force_approved": false,
"is_read": false,
"started_at": "2026-05-23T11:02:14.000000Z",
"last_activity_at": "2026-05-23T11:14:51.000000Z",
"finished_at": "2026-05-23T11:14:51.000000Z",
"deadline_at": null,
"status_updated_at": "2026-05-23T11:14:51.000000Z",
"checked_at": null,
"commented_at": null,
"canceled_at": null,
"passed_time_in_seconds": 757,
"crm_url": "https://lm4.kwiga.com/expert/practices?attempt_id=4821",
"user": {
"id": 712,
"name": "Alice Student",
"email": "alice@example.com"
},
"quiz": {
"id": 88,
"name": "Module 3 final test"
},
"course": {
"id": 226,
"product_id": 431,
"type": {
"id": 1,
"name": "Course",
"type": "course"
},
"title": "JS Foundations",
"slug": "js-foundations",
"url": "http://test.local/courses/js-foundations",
"status": {
"id": 3,
"name": "Published"
}
},
"lesson": {
"id": 504,
"title": "Closures & scope",
"course": {
"id": 226,
"product_id": 431,
"type_id": 1,
"title": "JS Foundations",
"url": "http://test.local/courses/js-foundations"
},
"module": {
"id": 30,
"course_id": 226,
"number": 3,
"title": "Functions in depth"
}
},
"product": {
"id": 431,
"productable_type": "course",
"productable_id": 226,
"name": "JS Foundations",
"url": "http://test.local/courses/js-foundations"
}
}
],
"links": {
"first": "https://api.kwiga.com/quiz-attempts?page=1",
"last": "https://api.kwiga.com/quiz-attempts?page=4",
"prev": null,
"next": "https://api.kwiga.com/quiz-attempts?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 4,
"path": "https://api.kwiga.com/quiz-attempts",
"per_page": 15,
"to": 15,
"total": 58,
"links": [
{ "url": null, "label": "« Previous", "active": false },
{ "url": "https://api.kwiga.com/quiz-attempts?page=1", "label": "1", "active": true },
{ "url": "https://api.kwiga.com/quiz-attempts?page=2", "label": "2", "active": false },
{ "url": "https://api.kwiga.com/quiz-attempts?page=2", "label": "Next »", "active": false }
]
},
"attempts_unread_count": 12
}
GET https://api.kwiga.com/quiz-attempts
Повертає посторінковий список спроб учнів за квізами, доступних
авторизованому куратору в усьому кабінеті (без прив'язки до
продукту в URL — передайте параметр products, щоб
звузити вибірку). За замовчуванням 15 елементів на сторінку,
максимум 250. Поле attempts_unread_count на верхньому
рівні показує кількість непрочитаних спроб з тим самим набором
фільтрів — зручно для «бейджа» нових спроб.
URL Parameters
151last_activity_atPossible values: last_activity_at, status_updated_at, finished_at, statusDefault: last_activity_atdescPossible values: asc, descDefault: descСтруктура відповіді
POST-аліас
POST https://api.kwiga.com/quiz-attempts/query
Функціональний аліас для GET-ендпоінта вище. Приймає ті самі параметри в тілі запиту замість query-string — стане в нагоді, коли список фільтрів завеликий для URL (або просто зручніше збирати JSON на клієнті). Body має пріоритет над query-string, форма відповіді ідентична.
Пропозиції
Отримання списку пропозицій
Приклад запиту:
<?php
// Get offers list filtered by product
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/offers?product_id=130', $options);
$result = json_decode($response->getBody());
?>
<?php
// Get offers list filtered by product
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/offers?product_id=130');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request GET 'https://api.kwiga.com/offers?product_id=130' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// Get offers list filtered by product
const url = 'https://api.kwiga.com/offers?product_id=130';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Get offers list filtered by product
import requests
url = 'https://api.kwiga.com/offers?product_id=130'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
{
"method": "GET",
"url": "https://api.kwiga.com/offers?product_id=130",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Приклад відповіді:
{
"data": [
{
"id": 273,
"unique_offer_code": "nELQzbLRPmzo",
"url": "https://kwiga.com/o/nELQzbLRPmzo",
"title": "This is paid offer for my course",
"description": "<p style=\"text-align: left\">Description with html.</p>",
"short_description": "<p style=\"text-align: left\">Shot description with html.</p>",
"price_type": {
"id": 2,
"name": "Платно"
},
"price": {
"amount": "10.00",
"amount_rounded": "10.00",
"amount_formatted": "10.00 usd",
"amount_formatted_code": "$10.00",
"amount_formatted_code_short": "$10.00",
"currency": {
"id": 5,
"code": "USD",
"html_code": "$",
"html_letter_code": "usd",
"is_volatile": false
}
},
"price_discounted": {
"amount": 5,
"amount_rounded": "5.00",
"amount_formatted": "5.00 usd",
"amount_formatted_code": "$5.00",
"amount_formatted_code_short": "$5.00",
"currency": {
"id": 5,
"code": "USD",
"html_code": "$",
"html_letter_code": "usd",
"is_volatile": false
}
},
"discount": {
"id": 3,
"price_discounted": 5,
"limit_type": {
"id": 1,
"name": "Безстроково"
},
"start_at": "2023-12-28T14:41:00.000000Z",
"start_at_utc": "2023-12-28T12:41:00.000000Z",
"start_timezone_id": 371,
"end_at": "2024-01-03T14:41:00.000000Z",
"end_type": 3,
"end_at_utc": "2024-01-03T12:41:00.000000Z",
"end_timezone_id": 371,
"sales_limit": null,
"sales": null,
"is_active": true,
"is_available": true,
"created_at": "2023-12-28T12:41:58.000000Z",
"updated_at": "2023-12-28T12:41:58.000000Z",
"start_timezone": {
"id": 371,
"name": "Europe/Kyiv",
"name_full": "Europe/Kyiv (UTC+03:00)",
"value": "UTC+03:00"
},
"end_timezone": {
"id": 371,
"name": "Europe/Kyiv",
"name_full": "Europe/Kyiv (UTC+03:00)",
"value": "UTC+03:00"
}
},
"has_subscription": false,
"limit_type": {
"id": 1,
"name": "Необмежено"
},
"limit_of_sales": null,
"is_active": true,
"is_draft": false,
"validity_start": {
"type": "validity_start",
"duration_type_id": 1,
"date_at": "2023-12-28T14:40:00.000000Z",
"date_at_utc": "2023-12-28T12:40:00.000000Z",
"timezone_id": 371,
"timezone": {
"id": 371,
"name": "Europe/Kyiv",
"name_full": "Europe/Kyiv (UTC+03:00)",
"value": "UTC+03:00"
},
"after_months": 0,
"after_days": 0,
"specific_time": null
},
"validity_end": {
"type": "validity_end",
"duration_type_id": 3,
"date_at": "2023-12-28T14:40:00.000000Z",
"date_at_utc": "2023-12-28T12:40:00.000000Z",
"timezone_id": 371,
"timezone": {
"id": 371,
"name": "Europe/Kyiv",
"name_full": "Europe/Kyiv (UTC+03:00)",
"value": "UTC+03:00"
},
"after_months": 0,
"after_days": 0,
"specific_time": null
},
"products": [
{
"id": 130,
"productable_id": 38,
"productable_type": "course",
"title": "This is my course",
"url": "https://kwiga.com/courses/test-fail"
}
]
},
{
"id": 272,
"unique_offer_code": "2obtMsUEujcy",
"url": "https://kwiga.com/o/2obtMsUEujcy",
"title": "This is free offer for my course",
"description": null,
"short_description": null,
"price_type": {
"id": 1,
"name": "Безкоштовно"
},
"price": {
"amount": "0.00",
"amount_rounded": "0.00",
"amount_formatted": "0.00 usd",
"amount_formatted_code": "$0.00",
"amount_formatted_code_short": "$0.00",
"currency": {
"id": 5,
"code": "USD",
"html_code": "$",
"html_letter_code": "usd",
"is_volatile": false
}
},
"price_discounted": {
"amount": 0,
"amount_rounded": "0.00",
"amount_formatted": "0.00 usd",
"amount_formatted_code": "$0.00",
"amount_formatted_code_short": "$0.00",
"currency": {
"id": 5,
"code": "USD",
"html_code": "$",
"html_letter_code": "usd",
"is_volatile": false
}
},
"discount": null,
"has_subscription": false,
"limit_type": {
"id": 1,
"name": "Необмежено"
},
"limit_of_sales": null,
"is_active": true,
"is_draft": false,
"validity_start": {
"type": "validity_start",
"duration_type_id": 1,
"date_at": "2023-12-27T12:45:00.000000Z",
"date_at_utc": "2023-12-27T10:45:00.000000Z",
"timezone_id": 371,
"timezone": {
"id": 371,
"name": "Europe/Kyiv",
"name_full": "Europe/Kyiv (UTC+03:00)",
"value": "UTC+03:00"
},
"after_months": 0,
"after_days": 0,
"specific_time": null
},
"validity_end": {
"type": "validity_end",
"duration_type_id": 3,
"date_at": "2023-12-27T12:45:00.000000Z",
"date_at_utc": "2023-12-27T10:45:00.000000Z",
"timezone_id": 371,
"timezone": {
"id": 371,
"name": "Europe/Kyiv",
"name_full": "Europe/Kyiv (UTC+03:00)",
"value": "UTC+03:00"
},
"after_months": 0,
"after_days": 0,
"specific_time": null
},
"products": [
{
"id": 130,
"productable_id": 38,
"productable_type": "course",
"title": "This is my course",
"url": "https://kwiga.com/courses/test-fail"
}
]
}
],
"links": {
"first": "http://api.kwiga.local/offers?page=1",
"last": "http://api.kwiga.local/offers?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"links": [
{
"url": null,
"label": "« Previous",
"active": false
},
{
"url": "http://api.kwiga.local/offers?page=1",
"label": "1",
"active": true
},
{
"url": null,
"label": "Next »",
"active": false
}
],
"path": "http://api.kwiga.local/offers",
"per_page": 15,
"to": 1,
"total": 2
}
}
GET https://api.kwiga.com/offers
URL Parameters
Структура відповіді
Отримання пропозиції
Приклад запиту:
<?php
// Get offer by ID
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/offers/:offer', $options);
$result = json_decode($response->getBody());
?>
<?php
// Get offer by ID
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/offers/:offer');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request GET 'https://api.kwiga.com/offers/:offer' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// Get offer by ID
const url = 'https://api.kwiga.com/offers/:offer';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Get offer by ID
import requests
url = 'https://api.kwiga.com/offers/:offer'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
{
"method": "GET",
"url": "https://api.kwiga.com/offers/:offer",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Приклад відповіді:
{
"data": {
"id": 1,
"unique_offer_code": "6rT1wj99lbZV",
"title": "Offer #1",
"limit_type": {
"id": 2,
"name": "Certain amount"
},
"limit_of_sales": 20,
"purchases_count": 1,
"sales_left": 19
}
}
GET https://api.kwiga.com/offers/:offer
Структура відповіді
Маркетинг. Розсилка
Список списків контактів
Приклад запиту:
<?php
// Get contact lists
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/mailing/contact-lists', $options);
$result = json_decode($response->getBody());
?>
# ---
# Paginated example
# ---
<?php
// Get contact lists with pagination
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/mailing/contact-lists?page=1&per_page=15', $options);
$result = json_decode($response->getBody());
?>
<?php
// Get contact lists
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/mailing/contact-lists');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
# ---
# Paginated example
# ---
<?php
// Get contact lists with pagination
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/mailing/contact-lists?page=1&per_page=15');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request GET 'https://api.kwiga.com/mailing/contact-lists' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
# ---
# Paginated example
# ---
curl --location --request GET 'https://api.kwiga.com/mailing/contact-lists?page=1&per_page=15' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// Get contact lists
const url = 'https://api.kwiga.com/mailing/contact-lists';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# ---
# Paginated example
# ---
// Get contact lists with pagination
const url = 'https://api.kwiga.com/mailing/contact-lists?page=1&per_page=15';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Get contact lists
import requests
url = 'https://api.kwiga.com/mailing/contact-lists'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
# ---
# Paginated example
# ---
# Get contact lists with pagination
import requests
url = 'https://api.kwiga.com/mailing/contact-lists?page=1&per_page=15'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
{
"method": "GET",
"url": "https://api.kwiga.com/mailing/contact-lists",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
# ---
# Paginated example
# ---
{
"method": "GET",
"url": "https://api.kwiga.com/mailing/contact-lists?page=1&per_page=15",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Приклад відповіді:
{
"data": [
{
"id": 2,
"title": "Пример 2",
"description": "Описание",
"is_default": false,
"created_at": "2022-04-28T13:22:44.000000Z",
"updated_at": "2022-04-28T13:22:44.000000Z"
},
{
"id": 1,
"title": "Мой первый список",
"description": "Данный список создаётся автоматически с вашим контактом внутри. Вы можете его отредактировать под свои потребности.",
"is_default": true,
"created_at": "2022-04-28T12:47:08.000000Z",
"updated_at": "2022-04-28T12:47:08.000000Z"
}
],
"links": {
"first": "https://api.kwiga.com/mailing/contact-lists?page=1",
"last": "https://api.kwiga.com/mailing/contact-lists?page=2",
"prev": null,
"next": "https://api.kwiga.com/mailing/contact-lists?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 2,
"links": [
{
"url": null,
"label": "« translation missing: ua.pagination_prev",
"active": false
},
{
"url": "https://api.kwiga.com/mailing/contact-lists?page=1",
"label": "1",
"active": true
},
{
"url": "https://api.kwiga.com/mailing/contact-lists?page=2",
"label": "2",
"active": false
},
{
"url": "https://api.kwiga.com/mailing/contact-lists?page=2",
"label": "translation missing: ua.pagination_next »",
"active": false
}
],
"path": "https://api.kwiga.com/mailing/contact-lists",
"per_page": 2,
"to": 2,
"total": 3
}
}
GET https://api.kwiga.com/mailing/contact-lists
URL Parameters
Структура відповіді
Отримання списку контактів
Приклад запиту:
<?php
// Get contact list by ID
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/mailing/contact-lists/:list', $options);
$result = json_decode($response->getBody());
?>
<?php
// Get contact list by ID
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/mailing/contact-lists/:list');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request GET 'https://api.kwiga.com/mailing/contact-lists/:list' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// Get contact list by ID
const url = 'https://api.kwiga.com/mailing/contact-lists/:list';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Get contact list by ID
import requests
url = 'https://api.kwiga.com/mailing/contact-lists/:list'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
{
"method": "GET",
"url": "https://api.kwiga.com/mailing/contact-lists/:list",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Приклад відповіді:
{
"data": {
"id": 1,
"title": "Мой первый список",
"description": "Данный список создаётся автоматически с вашим контактом внутри. Вы можете его отредактировать под свои потребности.",
"is_default": true,
"created_at": "2022-04-28T12:47:08.000000Z",
"updated_at": "2022-04-28T12:47:08.000000Z",
"contacts": [
{
"id": 1,
"first_name": "Alex",
"middle_name": null,
"last_name": "Иванович Burt",
"name": "Иванович Burt Alex",
"sex": null,
"age": null,
"email": "admin@grandstep.com.ua",
"phone_country": "UA",
"phone_number": "983721222",
"city": null,
"phone": "+380983721222",
"created_at": "2022-04-28T12:47:07.000000Z",
"updated_at": "2022-04-28T12:47:08.000000Z"
}
],
"statistic": {
"contact_list_id": 1,
"count_contacts": 1
}
}
}
GET https://api.kwiga.com/mailing/contact-lists/:list
Структура відповіді
Створення списку контактів
Приклад запиту:
<?php
// Create contact list
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
'json' => [
'title' => 'Название группы',
'description' => 'описание',
],
];
$response = $client->request('POST', '/mailing/contact-lists/', $options);
$result = json_decode($response->getBody());
?>
<?php
// Create contact list
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/mailing/contact-lists/');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$data = [
'title' => 'Название группы',
'description' => 'описание',
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request POST 'https://api.kwiga.com/mailing/contact-lists/' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>' \
--data-raw '{"title":"Название группы","description":"описание"}'
// Create contact list
const url = 'https://api.kwiga.com/mailing/contact-lists/';
const options = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
body: JSON.stringify({
'title': 'Название группы',
'description': 'описание'
})
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Create contact list
import requests
url = 'https://api.kwiga.com/mailing/contact-lists/'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
data = {
'title': 'Название группы',
'description': 'описание',
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
{
"method": "POST",
"url": "https://api.kwiga.com/mailing/contact-lists/",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"title": "Название группы",
"description": "описание"
}
}
Приклад відповіді:
{
"data": {
"id": 3,
"title": "fsdaf asfsf dsafsda fsda",
"description": "1dsad sadsa ds dsa",
"is_default": false,
"created_at": "2022-05-04T09:57:37.000000Z",
"updated_at": "2022-05-04T09:57:37.000000Z"
}
}
POST https://api.kwiga.com/mailing/contact-lists
Request
Структура відповіді
Додавання контактів до списку
Приклад запиту:
<?php
// Bulk add contacts to lists
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
'json' => [
'contacts[]' => 1,
'contacts[]' => 2,
'contact_lists[]' => 1,
],
];
$response = $client->request('POST', '/mailing/contact-lists/bulk-contacts', $options);
$result = json_decode($response->getBody());
?>
<?php
// Bulk add contacts to lists
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/mailing/contact-lists/bulk-contacts');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$data = [
'contacts[]' => 1,
'contacts[]' => 2,
'contact_lists[]' => 1,
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request POST 'https://api.kwiga.com/mailing/contact-lists/bulk-contacts' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>' \
--data-raw '{"contacts[]":2,"contact_lists[]":1}'
// Bulk add contacts to lists
const url = 'https://api.kwiga.com/mailing/contact-lists/bulk-contacts';
const options = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
body: JSON.stringify({
'contacts[]': 1,
'contacts[]': 2,
'contact_lists[]': 1
})
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Bulk add contacts to lists
import requests
url = 'https://api.kwiga.com/mailing/contact-lists/bulk-contacts'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
data = {
'contacts[]': 1,
'contacts[]': 2,
'contact_lists[]': 1,
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
{
"method": "POST",
"url": "https://api.kwiga.com/mailing/contact-lists/bulk-contacts",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"contacts[]": 2,
"contact_lists[]": 1
}
}
Приклад відповіді:
{
"success": true
}
POST https://api.kwiga.com/mailing/contact-lists/bulk-contacts
URL Parameters
Структура відповіді
Продажі. Купони
Список купонів
Приклад запиту:
<?php
// Get coupons list
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/coupons', $options);
$result = json_decode($response->getBody());
?>
# ---
# Filtered example
# ---
<?php
// Get coupons list with date filters
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/coupons?filters[date_from]=2022-04-15&filters[date_to]=2022-04-27', $options);
$result = json_decode($response->getBody());
?>
<?php
// Get coupons list
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/coupons');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
# ---
# Filtered example
# ---
<?php
// Get coupons list with date filters
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/coupons?filters[date_from]=2022-04-15&filters[date_to]=2022-04-27');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request GET 'https://api.kwiga.com/coupons' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
# ---
# Filtered example
# ---
curl --location --request GET 'https://api.kwiga.com/coupons?filters[date_from]=2022-04-15&filters[date_to]=2022-04-27' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// Get coupons list
const url = 'https://api.kwiga.com/coupons';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# ---
# Filtered example
# ---
// Get coupons list with date filters
const url = 'https://api.kwiga.com/coupons?filters[date_from]=2022-04-15&filters[date_to]=2022-04-27';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Get coupons list
import requests
url = 'https://api.kwiga.com/coupons'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
# ---
# Filtered example
# ---
# Get coupons list with date filters
import requests
url = 'https://api.kwiga.com/coupons?filters[date_from]=2022-04-15&filters[date_to]=2022-04-27'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
{
"method": "GET",
"url": "https://api.kwiga.com/coupons",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
# ---
# Filtered example
# ---
{
"method": "GET",
"url": "https://api.kwiga.com/coupons?filters[date_from]=2022-04-15&filters[date_to]=2022-04-27",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Приклад відповіді:
{
"data": [
{
"id": 3,
"code": "KwigaSMVT-MD",
"reward": 30,
"is_fixed": true,
"is_disposable": false,
"used_amount": 0,
"total_uses": 10,
"total_uses_per_user": 1,
"user": {
"id": 3,
"avatar_url": "https://someurl.com",
"hash": "EL9p2ycy4Ypga715",
"name": "Test User",
"email": "test@example.com",
"tag_name": "TestUser"
},
"created_at": "2022-04-28T09:46:11.000000Z",
"updated_at": "2022-04-28T09:46:11.000000Z",
"deleted_at": null
}
]
}
GET https://api.kwiga.com/coupons
URL Parameters
Структура відповіді
Отримання купона
Приклад запиту:
<?php
// Get coupon by ID
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/coupons/:coupon', $options);
$result = json_decode($response->getBody());
?>
<?php
// Get coupon by ID
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/coupons/:coupon');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request GET 'https://api.kwiga.com/coupons/:coupon' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// Get coupon by ID
const url = 'https://api.kwiga.com/coupons/:coupon';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Get coupon by ID
import requests
url = 'https://api.kwiga.com/coupons/:coupon'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
{
"method": "GET",
"url": "https://api.kwiga.com/coupons/:coupon",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Приклад відповіді:
{
"data": {
"id": 1,
"code": "KwigaSMVT-MD",
"reward": 30,
"is_fixed": true,
"is_disposable": false,
"used_amount": 0,
"total_uses": 10,
"total_uses_per_user": 1,
"created_at": "2022-04-28T09:46:11.000000Z",
"updated_at": "2022-04-28T09:46:11.000000Z",
"deleted_at": null
}
}
GET https://api.kwiga.com/coupons/:coupon
Структура відповіді
Створити купон
Приклад запиту:
<?php
// Create coupon
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
'json' => [
'code' => 'MY-COUPON',
'reward' => 0,
'type_discount[id]' => 'discount_with_percent',
'expires_at' => ,
'timezone[id]' => 375,
'total_uses' => 0,
'total_uses_per_user' => 0,
],
];
$response = $client->request('POST', '/coupons', $options);
$result = json_decode($response->getBody());
?>
<?php
// Create coupon
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/coupons');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$data = [
'code' => 'MY-COUPON',
'reward' => 0,
'type_discount[id]' => 'discount_with_percent',
'expires_at' => ,
'timezone[id]' => 375,
'total_uses' => 0,
'total_uses_per_user' => 0,
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request POST 'https://api.kwiga.com/coupons' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>' \
--data-raw '{"code":"MY-COUPON","reward":0,"type_discount[id]":"discount_with_percent","expires_at":null,"timezone[id]":375,"total_uses":0,"total_uses_per_user":0}'
// Create coupon
const url = 'https://api.kwiga.com/coupons';
const options = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
body: JSON.stringify({
'code': 'MY-COUPON',
'reward': 0,
'type_discount[id]': 'discount_with_percent',
'expires_at': ,
'timezone[id]': 375,
'total_uses': 0,
'total_uses_per_user': 0
})
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Create coupon
import requests
url = 'https://api.kwiga.com/coupons'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
data = {
'code': 'MY-COUPON',
'reward': 0,
'type_discount[id]': 'discount_with_percent',
'expires_at': ,
'timezone[id]': 375,
'total_uses': 0,
'total_uses_per_user': 0,
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
{
"method": "POST",
"url": "https://api.kwiga.com/coupons",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"code": "MY-COUPON",
"reward": 0,
"type_discount[id]": "discount_with_percent",
"expires_at": null,
"timezone[id]": 375,
"total_uses": 0,
"total_uses_per_user": 0
}
}
Приклад відповіді:
{
"data": {
"id": 8,
"code": "MY-COUPON",
"reward": 100,
"type_discount": {
"id": "discount_with_percent",
"name": "In % of order/offer value"
},
"type_date_expired": {
"id": "indefinite_action",
"name": "Never expires"
},
"type_total_count_used": {
"id": "certain_amount",
"name": "A certain amount"
},
"type_used_contact_lists": {
"id": "all_users",
"name": "All users"
},
"is_fixed": false,
"is_active": true,
"used_amount": 0,
"has_infinite_used": true,
"has_access_contact_lists": false,
"total_uses": 0,
"total_uses_per_user": 1,
"contact_lists": [],
"type": {
"id": 4,
"title": "Offers"
},
"expires_at": null,
"expires_at_utc": null,
"timezone_id": null,
"currency_id": null,
"currency": null,
"created_at": "2024-01-09T16:17:55.000000Z",
"updated_at": "2024-01-09T16:17:55.000000Z",
"deleted_at": null
}
}
POST https://api.kwiga.com/coupons
URL Parameters
discount_with_percent or discount_with_currency2024-12-31 or 2024-12-31 23:59:59Структура відповіді
Перевірка купона
Приклад запиту:
<?php
// Check coupon validity
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
'json' => [
'code' => 'VAJ6-EA',
'price' => 65,
],
];
$response = $client->request('POST', '/coupons/check', $options);
$result = json_decode($response->getBody());
?>
<?php
// Check coupon validity
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/coupons/check');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$data = [
'code' => 'VAJ6-EA',
'price' => 65,
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request POST 'https://api.kwiga.com/coupons/check' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>' \
--data-raw '{"code":"VAJ6-EA","price":65}'
// Check coupon validity
const url = 'https://api.kwiga.com/coupons/check';
const options = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
body: JSON.stringify({
'code': 'VAJ6-EA',
'price': 65
})
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Check coupon validity
import requests
url = 'https://api.kwiga.com/coupons/check'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
data = {
'code': 'VAJ6-EA',
'price': 65,
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
{
"method": "POST",
"url": "https://api.kwiga.com/coupons/check",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"code": "VAJ6-EA",
"price": 65
}
}
Приклад відповіді:
{
"data": {
"can_use": true,
"discount": 6.5
}
}
POST https://api.kwiga.com/coupons/check
Перевіряє купон на існування і можливість використання (не вичерпано ліміт / не закінчився термін дії).
Зверніть увагу: при використанні на checkout сторінці купон може не застосовуватися при наступних умовах: якщо на пропозиції вимкнено використання купонів/даного купона; на купоні є обмеження списками контактів; користувач вже використовував купон і на купоні є обмеження по кількості використань.
Parameters
Структура відповіді
Сертифікати
Отримання сертифікат за номером
Приклад запиту:
<?php
// Get certificate by number
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/certificates/by-number/:number', $options);
$result = json_decode($response->getBody());
?>
<?php
// Get certificate by number
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/certificates/by-number/:number');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request GET 'https://api.kwiga.com/certificates/by-number/:number' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// Get certificate by number
const url = 'https://api.kwiga.com/certificates/by-number/:number';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Get certificate by number
import requests
url = 'https://api.kwiga.com/certificates/by-number/:number'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
{
"method": "GET",
"url": "https://api.kwiga.com/certificates/by-number/:number",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Приклад відповіді:
{
"data": {
"id": 55,
"uuid": "262e7042-1933-42a9-ba01-e96d7d5110dc",
"cabinet_id": 1,
"user_id": 273,
"issued_at": "2023-07-25T15:36:44.000000Z",
"number": "1986-0001",
"url": "http://cabinet-1.kwiga.local/certificates/262e7042-1933-42a9-ba01-e96d7d5110dc",
"created_at": "2023-07-25T15:36:44.000000Z",
"updated_at": "2023-07-25T15:36:44.000000Z",
"finished_at": "2023-07-25T15:36:44.000000Z",
"points": 120,
"user": {
"id": 273,
"name": "test name",
"email": "test-student@kwiga.com"
},
"certificateble_title": "Test course"
}
}
GET https://api.kwiga.com/certificates/by-number/:number
Структура відповіді
Таймзони
Отримання списку таймзон
Приклад запиту:
<?php
// Get timezones list
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.kwiga.com']);
$options = [
'headers' => [
'Accept' => 'application/json',
'Token' => '<Token>',
'Cabinet-Hash' => '<Cabinet-Hash>',
],
];
$response = $client->request('GET', '/timezones', $options);
$result = json_decode($response->getBody());
?>
<?php
// Get timezones list
$headers = [
'Accept: application/json',
'Token: <Token>',
'Cabinet-Hash: <Cabinet-Hash>',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.kwiga.com/timezones');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response);
?>
curl --location --request GET 'https://api.kwiga.com/timezones' \
--header 'Content-Type: application/json' \
--header 'Token: <Token>' \
--header 'Cabinet-Hash: <Cabinet-Hash>'
// Get timezones list
const url = 'https://api.kwiga.com/timezones';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
},
};
fetch(url, options)
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error);
});
# Get timezones list
import requests
url = 'https://api.kwiga.com/timezones'
headers = {
'Accept': 'application/json',
'Token': '<Token>',
'Cabinet-Hash': '<Cabinet-Hash>',
}
response = requests.get(url, headers=headers)
result = response.json()
{
"method": "GET",
"url": "https://api.kwiga.com/timezones",
"headers": {
"Token": "<Token>",
"Cabinet-Hash": "<Cabinet-Hash>",
"Accept": "application/json"
}
}
Приклад відповіді:
{
"data": [
{
"id": 1,
"name": "Asia/Kabul",
"name_full": "Asia/Kabul (UTC+04:30)",
"value": "UTC+04:30"
},
{
"id": 2,
"name": "Europe/Tirane",
"name_full": "Europe/Tirane (UTC+02:00)",
"value": "UTC+02:00"
},
...
]
}
GET https://api.kwiga.com/timezones
Структура відповіді
Схеми даних
Перевикористовувані об'єкти відповідей API. Поля з позначкою conditional з'являються у відповіді лише за виконання документованої умови (прапор запиту, опціональний include чи певний ендпоінт).
Контакти
Contact
Теги, прикріплені до контакту
Момент останньої активності контакту в кабінеті
Перший зафіксований візит контакту
Агрегована UTM-атрибуція за всіма візитами контакту
Усі UTM-відстежені візити контакту
Пропозиції, куплені контактом
Замовлення, розміщені контактом
Кастомні поля кабінету, заповнені для цього контакту
Інформація про випущені сертифікати за продуктами контакту
ContactIdentifier
ContactAdditionalField
Визначення кастомного поля кабінету
ContactField
Токен формату вводу для поля
Вираз правила валідації
Ідентифікатор типу поля (text, number, date, enum тощо)
Порядок відображення всередині кабінету
Допустимі значення для enum-полів
Порядок відображення імені/прізвища, заданий у кабінеті
ContactList
Ідентифікатор кабінету-власника
Ідентифікатор користувача-власника
Email-розсилки, пов'язані зі списком
Правила фільтрації, що визначають членство в сегменті
ContactListStatistic
FlowTag
Скільки контактів позначено цим тегом
Курси
Course
CourseIdentify
Короткі ідентифікаційні записи уроків курсу
URL прев'ю-картинки курсу (або плейсхолдер за замовчуванням, якщо зображення не задано)
Короткі ідентифікаційні записи пропозицій, пов'язаних з курсом
CourseLessonIdentify
CourseLessonSimple
Квізи, прикріплені до уроку
Ідентифікаційні дані батьківського курсу
CourseModuleSimple
CourseProgram
CourseProgress
CourseUser
include contains lesson_progress.Масив об'єктів `LessonProgress` — per-lesson знімки перегляду/завершення для цього користувача. Повертається при `include=lesson_progress`.
include contains module_progress.Масив об'єктів `ModuleProgress` — per-module знімки перегляду/завершення для цього користувача (агрегуються сервером з уроків модуля). Повертається при `include=module_progress`.
include contains quiz_progress.Масив об'єктів `QuizProgress` — по одному запису на пару `(course_lesson_id, quiz_id)` зі зведенням за останньою non-cancelled спробою учня. Повертається при `include=quiz_progress`.
InfoUnit
QuizIdentifier
QuizAttemptIdentifier
Метадані квіза
Метадані уроку
Купони
ExpertCoupon
Метадані типу купона
Короткі ідентифікаційні дані пов'язаного контакту
Ідентифікаційні дані пропозицій, на які діє купон
Останній внутрішній коментар (для адміністраторів)
CouponType
CouponCheck
Сертифікати
Certificate
Коли користувач завершив certificateble-сутність (курс тощо)
Бали, набрані користувачем для отримання сертифіката
CertificateTemplate
StudentProductCertificateInfo
Назва certificateble-сутності
Пропозиції
Offer
Ціна із застосованою активною знижкою
OfferIdentifier
OfferSimple
OfferDiscount
Короткі ідентифікаційні дані батьківської пропозиції
Замовлення
Order
OrderFunnel
OrderGroup
OrderStage
Платежі
Payment
Transaction
Price
Currency
Продукти
Product
Публічне посилання на productable-сутність
ProductIdentifier
ProductAggregatedSubscription
ProductSubscription
UserProduct
Агрегована інформація про доступ (загальний is_active/start/end за всіма підписками)
Окремі записи підписок (по одній на замовлення/пропозицію)
EmailCampaign
Дані email-шаблону (системний або кастомний)
Повний знімок статистики розсилки
EmailCampaignIdentifier
Візити
Visit
Інформація про user agent / пристрій
VisitLocation
VisitUserAgent
UtmList
Коментарі
CommentIdentifier
Короткий payload цільової сутності
Спроби квізів
QuizAttempt
Статус спроби у вигляді enum-об'єкта — id (числове значення), slug (стабільне ім'я кейса) та title (підпис, уже перекладений під локаль кабінету).
1— Пройдено2— Не пройдено3— Потрібне доопрацювання4— Остання версія змінила статус5— У процесі6— Очікує перевірки7— Не розпочав
InfoSectionReport
Нагороди (гейміфікація)
FlowRewardLog
points — accrued або deducted. Збігається зі значеннями фільтра accrual_type у списку.
Чому з''явився цей запис. Можливі id:
1— Практика пройдена2— Скасування результатів практики3— Скидання балів за спробу4— Нові бали за спробу5— Оплата балами6— Вручну7— Автоматизація8— Змінено бали за спробу9— Оплата балами за подарунок
event). Для ручних — NULL.
quiz_attempt, order, gift). Для ручних — NULL.
eventable_type. Для ручних — NULL.
manual_comment учневі в його власному журналі балів. Для не-ручних записів — NULL. Куратори (включно з цим API) бачать коментар завжди, незалежно від прапору.