Payroll
Finance · 11 операцій
/api/payrollGETGet payroll/api/payroll/{id}GETGet teacher payout/api/payroll/payout/{id}POSTSend payouts to teachers/api/payroll/payout/sendPOSTRecall payouts from teachers/api/payroll/payout/recallPOSTConfirm payouts for teachers/api/payroll/payout/skip-teacher-reviewPOSTMark payouts ready to pay/api/payroll/payout/readyPOSTUnmark payouts ready to pay/api/payroll/payout/unreadyPOSTRecord payouts as paid/api/payroll/payout/payPOSTCancel payout payments/api/payroll/payout/cancel-paymentPOSTRecalculate teacher payout/api/payroll/payout/{id}/recalculateList payrolls
/api/payrollSalary payroll batches: period, number of payouts, totals paid and unpaid, counts by payout status. Filter by teacherIds, payoutMethods or accountIds (where a paid payout went, or the teacher account an unpaid one will be paid from).
list_payrolls
Параметри запиту · 3
teacherIds—payoutMethodsPayout method from the teacher's current requisites, not as of the payment.Одне з: CARD IBAN CASHaccountIdsWhere a paid payout went, or the teacher's current account an unpaid one will be paid from.Відповідь · 200
application/json
statusCodeприклад 200message—data10 полів
payrollId—periodFrom—periodTo—withTeacherReview—createdAtформат YYYY-MM-DDTHH:mm:sspayoutCount—paidCount—total—paidTotal—lastPaidAtWhen the last teacher of the payroll was paid.формат YYYY-MM-DDTHH:mm:sscurl "https://your-school.rist.pro/api/payroll" \
-H "Authorization: Bearer $RIST_API_KEY"const response = await fetch("https://your-school.rist.pro/api/payroll", {
headers: {
Authorization: `Bearer ${process.env.RIST_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://your-school.rist.pro/api/payroll",
headers={"Authorization": f"Bearer {os.environ['RIST_API_KEY']}"},
)
response.raise_for_status()
data = response.json()["data"]{
"statusCode": 200,
"message": "Operation completed successfully",
"data": [
{
"payrollId": 1,
"periodFrom": "string",
"periodTo": "string",
"withTeacherReview": false,
"createdAt": "2026-11-09T14:30:00",
"payoutCount": 0,
"paidCount": 0,
"total": 0,
"paidTotal": 0,
"lastPaidAt": "2026-11-09T14:30:00"
}
]
}Get payroll
/api/payroll/{id}One payroll batch with each teacher payout: status, lesson count, wage, bonus, penalty and correction totals, warnings.
get_payroll
Параметри шляху · 1
id—Відповідь · 200
application/json
statusCodeприклад 200message—data8 полів
payrollId—periodFromYYYY-MM-DDperiodTo—withTeacherReview—includeBonuses—includePenalties—splitFromFirst day of the second part (YYYY-MM-DD): each payout is paid as two operations.createdAtформат YYYY-MM-DDTHH:mm:sscurl "https://your-school.rist.pro/api/payroll/1" \
-H "Authorization: Bearer $RIST_API_KEY"const response = await fetch("https://your-school.rist.pro/api/payroll/1", {
headers: {
Authorization: `Bearer ${process.env.RIST_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://your-school.rist.pro/api/payroll/1",
headers={"Authorization": f"Bearer {os.environ['RIST_API_KEY']}"},
)
response.raise_for_status()
data = response.json()["data"]{
"statusCode": 200,
"message": "Operation completed successfully",
"data": {
"payrollId": 1,
"periodFrom": "string",
"periodTo": "string",
"withTeacherReview": false,
"includeBonuses": false,
"includePenalties": false,
"splitFrom": "string",
"createdAt": "2026-11-09T14:30:00"
}
}Get teacher payout
/api/payroll/payout/{id}One teacher payout: totals, status, wage and bonus balances included, event history (sent, confirmed, questions) and the finance operation once paid.
get_payroll_payout
Параметри шляху · 1
id—Відповідь · 200
application/json
statusCodeприклад 200message—data21 поле
periodFrom—periodTo—withTeacherReview—noChargeLessonCountCount of period lessons without accrual; the lessons themselves come from GET …/lessons.splitFromFirst day of the second part (YYYY-MM-DD) when the payroll is paid in two parts.payrollPayoutId—payrollId—statusОдне з: PREPARED CONFIRMED QUESTION READY PAID TEACHER_REVIEWtotal—paidAtформат YYYY-MM-DDTHH:mm:ssquestion—excludedBonusIds—teacher11 полів
teacherId—firstName—lastName—middleName—avatarUrl—hasAccount—payoutMethodRequisites only with the teacher.payoutDetails field permission (or the permission to pay).Одне з: CARD IBAN CASHpayoutRecipient—payoutDetails—payoutNote—payoutAccount2 поля
accountId—nameOfAccount—account2 поля
accountId—nameOfAccount—lessonCountLessons under wages (without corrections) and their duration.durationMinutes—wageTotal—bonusTotal—penaltyTotal—correctionTotal—unconductedLessonCountPeriod lessons already over but still scheduled (neither conducted nor cancelled).curl "https://your-school.rist.pro/api/payroll/payout/1" \
-H "Authorization: Bearer $RIST_API_KEY"const response = await fetch("https://your-school.rist.pro/api/payroll/payout/1", {
headers: {
Authorization: `Bearer ${process.env.RIST_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://your-school.rist.pro/api/payroll/payout/1",
headers={"Authorization": f"Bearer {os.environ['RIST_API_KEY']}"},
)
response.raise_for_status()
data = response.json()["data"]{
"statusCode": 200,
"message": "Operation completed successfully",
"data": {
"periodFrom": "string",
"periodTo": "string",
"withTeacherReview": false,
"noChargeLessonCount": 0,
"splitFrom": "string",
"payrollPayoutId": 1,
"payrollId": 1,
"status": "PREPARED",
"total": 0,
"paidAt": "2026-11-09T14:30:00",
"question": "string",
"excludedBonusIds": [
1
],
"teacher": {
"teacherId": 1,
"firstName": "string",
"lastName": "string",
"middleName": "string",
"avatarUrl": "string",
"hasAccount": false,
"payoutMethod": "CARD",
"payoutRecipient": "string",
"payoutDetails": "string",
"payoutNote": "string",
"payoutAccount": {
"accountId": 1,
"nameOfAccount": "string"
}
},
"account": {
"accountId": 1,
"nameOfAccount": "string"
},
"lessonCount": 0,
"durationMinutes": 0,
"wageTotal": 0,
"bonusTotal": 0,
"penaltyTotal": 0,
"correctionTotal": 0,
"unconductedLessonCount": 0
}
}Send payouts to teachers
/api/payroll/payout/sendSend payouts to their teachers for confirmation: PREPARED or QUESTION → TEACHER_REVIEW; a payout with a question is recalculated and sent with the new total. Only in a payroll with teacher review, for teachers with a CRM account. May trigger school automations. ids are payrollPayoutId values from GET /api/payroll/{id}; all of them move in one transaction, so one payout that cannot move fails the whole call.
send_payroll_payouts
Тіло запиту
application/json · object
idsмін. 1 · елементів мін. 1Відповідь · 201
application/json
curl -X POST "https://your-school.rist.pro/api/payroll/payout/send" \
-H "Authorization: Bearer $RIST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"ids": [
1
]
}'const response = await fetch("https://your-school.rist.pro/api/payroll/payout/send", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RIST_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"ids": [
1
]
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://your-school.rist.pro/api/payroll/payout/send",
headers={"Authorization": f"Bearer {os.environ['RIST_API_KEY']}"},
json={
"ids": [
1
]
},
)
response.raise_for_status()
data = response.json()["data"]{
"statusCode": 201,
"message": "Operation completed successfully",
"data": {
"count": 0
}
}Recall payouts from teachers
/api/payroll/payout/recallOne step back from the teacher: TEACHER_REVIEW or QUESTION → PREPARED, CONFIRMED → TEACHER_REVIEW (→ PREPARED when the teacher does not review). Lines and totals stay. A return to TEACHER_REVIEW may trigger school automations, as sending does. ids are payrollPayoutId values from GET /api/payroll/{id}; all of them move in one transaction, so one payout that cannot move fails the whole call.
recall_payroll_payouts
Тіло запиту
application/json · object
idsмін. 1 · елементів мін. 1Відповідь · 201
application/json
curl -X POST "https://your-school.rist.pro/api/payroll/payout/recall" \
-H "Authorization: Bearer $RIST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"ids": [
1
]
}'const response = await fetch("https://your-school.rist.pro/api/payroll/payout/recall", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RIST_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"ids": [
1
]
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://your-school.rist.pro/api/payroll/payout/recall",
headers={"Authorization": f"Bearer {os.environ['RIST_API_KEY']}"},
json={
"ids": [
1
]
},
)
response.raise_for_status()
data = response.json()["data"]{
"statusCode": 201,
"message": "Operation completed successfully",
"data": {
"count": 0
}
}Confirm payouts for teachers
/api/payroll/payout/skip-teacher-reviewConfirm for teachers who approved the amount outside the CRM: PREPARED, TEACHER_REVIEW or QUESTION → CONFIRMED, the question is cleared. comment says how the teacher approved and goes to the payout history. Only in a payroll with teacher review, for teachers with a CRM account. ids are payrollPayoutId values from GET /api/payroll/{id}; all of them move in one transaction, so one payout that cannot move fails the whole call.
skip_payroll_teacher_review
Тіло запиту
application/json · object
idsмін. 1 · елементів мін. 1commentHow the teacher approved the amount outside the CRM (e.g. by phone); saved to the payout history.довжина макс. 1500Відповідь · 201
application/json
curl -X POST "https://your-school.rist.pro/api/payroll/payout/skip-teacher-review" \
-H "Authorization: Bearer $RIST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"ids": [
1
],
"comment": "string"
}'const response = await fetch("https://your-school.rist.pro/api/payroll/payout/skip-teacher-review", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RIST_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"ids": [
1
],
"comment": "string"
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://your-school.rist.pro/api/payroll/payout/skip-teacher-review",
headers={"Authorization": f"Bearer {os.environ['RIST_API_KEY']}"},
json={
"ids": [
1
],
"comment": "string"
},
)
response.raise_for_status()
data = response.json()["data"]{
"statusCode": 201,
"message": "Operation completed successfully",
"data": {
"count": 0
}
}Mark payouts ready to pay
/api/payroll/payout/readyMark payouts as checked and ready to pay: CONFIRMED → READY, or PREPARED → READY when the teacher does not review (payroll without review or teacher without a CRM account). ids are payrollPayoutId values from GET /api/payroll/{id}; all of them move in one transaction, so one payout that cannot move fails the whole call.
mark_payroll_payouts_ready
Тіло запиту
application/json · object
idsмін. 1 · елементів мін. 1Відповідь · 201
application/json
curl -X POST "https://your-school.rist.pro/api/payroll/payout/ready" \
-H "Authorization: Bearer $RIST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"ids": [
1
]
}'const response = await fetch("https://your-school.rist.pro/api/payroll/payout/ready", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RIST_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"ids": [
1
]
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://your-school.rist.pro/api/payroll/payout/ready",
headers={"Authorization": f"Bearer {os.environ['RIST_API_KEY']}"},
json={
"ids": [
1
]
},
)
response.raise_for_status()
data = response.json()["data"]{
"statusCode": 201,
"message": "Operation completed successfully",
"data": {
"count": 0
}
}Unmark payouts ready to pay
/api/payroll/payout/unreadyOne step back from ready to pay: READY → CONFIRMED (→ PREPARED when the teacher does not review). Lines and totals stay. ids are payrollPayoutId values from GET /api/payroll/{id}; all of them move in one transaction, so one payout that cannot move fails the whole call.
unready_payroll_payouts
Тіло запиту
application/json · object
idsмін. 1 · елементів мін. 1Відповідь · 201
application/json
curl -X POST "https://your-school.rist.pro/api/payroll/payout/unready" \
-H "Authorization: Bearer $RIST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"ids": [
1
]
}'const response = await fetch("https://your-school.rist.pro/api/payroll/payout/unready", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RIST_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"ids": [
1
]
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://your-school.rist.pro/api/payroll/payout/unready",
headers={"Authorization": f"Bearer {os.environ['RIST_API_KEY']}"},
json={
"ids": [
1
]
},
)
response.raise_for_status()
data = response.json()["data"]{
"statusCode": 201,
"message": "Operation completed successfully",
"data": {
"count": 0
}
}Record payouts as paid
/api/payroll/payout/payRecord payouts as paid: READY → PAID. Creates a wage expense operation per payout and takes the amounts off the teacher rate and bonus balances; a split payroll gets one operation per part, unless a part has nothing to pay. The first part of a split payroll is dated firstPartDateOfOperation (default: the last day of that part), everything else dateOfOperation (YYYY-MM-DD, school day). accountId pays every id from that account instead of each teacher's payout account (account in GET /api/payroll/{id}); pass it only when the person named the account, otherwise leave it out. 409 when a teacher has no account and accountId is not given, or when accruals changed after the calculation (POST /api/payroll/payout/{id}/recalculate first); 403 when the account is not available to your role; 400 when a payout total is zero or negative. Returns count and total. ids are payrollPayoutId values from GET /api/payroll/{id}; all of them move in one transaction, so one payout that cannot move fails the whole call.
pay_payroll_payouts
Тіло запиту
application/json · object
idsмін. 1 · елементів мін. 1dateOfOperation—firstPartDateOfOperationOperation date of the first part of a split payroll; left out — the last day of that part.accountIdOverrides the account in each teacher's payout details; the details themselves stay unchanged.мін. 1Відповідь · 201
application/json
statusCodeприклад 201message—data2 поля
countPayouts paid.totalSum paid, in the school currency.curl -X POST "https://your-school.rist.pro/api/payroll/payout/pay" \
-H "Authorization: Bearer $RIST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"ids": [
1
],
"dateOfOperation": "string",
"firstPartDateOfOperation": "string",
"accountId": 1
}'const response = await fetch("https://your-school.rist.pro/api/payroll/payout/pay", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RIST_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"ids": [
1
],
"dateOfOperation": "string",
"firstPartDateOfOperation": "string",
"accountId": 1
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://your-school.rist.pro/api/payroll/payout/pay",
headers={"Authorization": f"Bearer {os.environ['RIST_API_KEY']}"},
json={
"ids": [
1
],
"dateOfOperation": "string",
"firstPartDateOfOperation": "string",
"accountId": 1
},
)
response.raise_for_status()
data = response.json()["data"]{
"statusCode": 201,
"message": "Operation completed successfully",
"data": {
"count": 0,
"total": 0
}
}Cancel payout payments
/api/payroll/payout/cancel-paymentCancel payments: PAID → READY. Deletes the wage operations and returns the amounts to the rate and bonus balances; lines stay. Only the newest payout of a teacher can be cancelled, otherwise 409. ids are payrollPayoutId values from GET /api/payroll/{id}; all of them move in one transaction, so one payout that cannot move fails the whole call.
cancel_payroll_payments
Тіло запиту
application/json · object
idsмін. 1 · елементів мін. 1Відповідь · 201
application/json
curl -X POST "https://your-school.rist.pro/api/payroll/payout/cancel-payment" \
-H "Authorization: Bearer $RIST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"ids": [
1
]
}'const response = await fetch("https://your-school.rist.pro/api/payroll/payout/cancel-payment", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RIST_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"ids": [
1
]
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://your-school.rist.pro/api/payroll/payout/cancel-payment",
headers={"Authorization": f"Bearer {os.environ['RIST_API_KEY']}"},
json={
"ids": [
1
]
},
)
response.raise_for_status()
data = response.json()["data"]{
"statusCode": 201,
"message": "Operation completed successfully",
"data": {
"count": 0
}
}Recalculate teacher payout
/api/payroll/payout/{id}/recalculateRecalculate one unpaid payout from current accruals (lessons conducted or rolled back, changed rates) and return it to PREPARED, so the review starts again. 409 for a paid payout.
recalculate_payroll_payout
Параметри шляху · 1
id—Відповідь · 201
application/json
statusCodeприклад 201message—data1 поле
payrollPayoutIdThe recalculated payout; read it again for the new amounts.curl -X POST "https://your-school.rist.pro/api/payroll/payout/1/recalculate" \
-H "Authorization: Bearer $RIST_API_KEY"const response = await fetch("https://your-school.rist.pro/api/payroll/payout/1/recalculate", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RIST_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://your-school.rist.pro/api/payroll/payout/1/recalculate",
headers={"Authorization": f"Bearer {os.environ['RIST_API_KEY']}"},
)
response.raise_for_status()
data = response.json()["data"]{
"statusCode": 201,
"message": "Operation completed successfully",
"data": {
"payrollPayoutId": 1
}
}