API reference
Compliance
Suspicious-activity cases and communications to GIFiM (F3-8), compliance:* only.
GET /v1/admin/compliance/cases
List suspicious-activity cases
Suspicious-activity cases (F3-8) are opened by an operator or by a risk rule marked suspicion, investigated (notes), and decided — report to GIFiM or not — with a justification by one compliance officer and approval by another. They belong to the platform: only keys with compliance:read/compliance:write reach them (admin:* does not), and nothing about a case reaches the customer or the partner (no tipping-off). Requires compliance:read.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
status | query | string |
Responses
- 200
{data, total}, open first.
Request
curl -X GET "$KULPAY_URL/v1/admin/compliance/cases" \ -H "Authorization: Bearer $KULPAY_KEY"
200 Response application/json
{
"data": [
{
"account_id": "3KZlyE2fG4hI6jK8lM0nO2pQ4rS",
"created_at": "2026-10-12T09:00:00Z",
"id": "3KZm0Cs1Dt2Eu3Fv4Gw5Hx6Iy7J",
"opened_by": "system:risk",
"rule_id": "structuring",
"source": "risk_rule",
"status": "open",
"subject_id": "3KZlzP9qR1sT3uV5wX7yZ9aB1cD",
"subject_type": "transaction",
"summary": "risk rule structuring fired (review): amount 950 MZN at or above 900"
}
],
"total": 1
}
POST /v1/admin/compliance/cases
Open a case
Requires compliance:write.
Request body application/json required
| Field | Type | Description |
|---|---|---|
account_id | string | |
subject_id required | string | |
subject_type required | string | |
summary required | string |
Responses
- 201 The case.
Request
curl -X POST "$KULPAY_URL/v1/admin/compliance/cases" \
-H "Authorization: Bearer $KULPAY_KEY" \
-H "Content-Type: application/json" \
-d '{
"subject_id": "3KZlzP9qR1sT3uV5wX7yZ9aB1cD",
"subject_type": "cash_deposit",
"summary": "three deposits of 240 000 MZN in a day by the same depositor"
}'
201 Response application/json
{
"account_id": "3KZlyE2fG4hI6jK8lM0nO2pQ4rS",
"created_at": "2026-10-12T09:00:00Z",
"id": "3KZm0Cs1Dt2Eu3Fv4Gw5Hx6Iy7J",
"opened_by": "system:risk",
"rule_id": "structuring",
"source": "risk_rule",
"status": "open",
"subject_id": "3KZlzP9qR1sT3uV5wX7yZ9aB1cD",
"subject_type": "transaction",
"summary": "risk rule structuring fired (review): amount 950 MZN at or above 900"
}
GET /v1/admin/compliance/cases/{id}
Get a case
Requires compliance:read.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string |
Responses
- 200 The case.
Request
curl -X GET "$KULPAY_URL/v1/admin/compliance/cases/{id}" \
-H "Authorization: Bearer $KULPAY_KEY"
200 Response application/json
{
"account_id": "3KZlyE2fG4hI6jK8lM0nO2pQ4rS",
"created_at": "2026-10-12T09:00:00Z",
"id": "3KZm0Cs1Dt2Eu3Fv4Gw5Hx6Iy7J",
"opened_by": "system:risk",
"rule_id": "structuring",
"source": "risk_rule",
"status": "open",
"subject_id": "3KZlzP9qR1sT3uV5wX7yZ9aB1cD",
"subject_type": "transaction",
"summary": "risk rule structuring fired (review): amount 950 MZN at or above 900"
}
POST /v1/admin/compliance/cases/{id}/approve
Approve a case's decision (checker)
The second compliance officer; the one who decided gets 403 same_approver. Approved, the case is reported or closed. Requires compliance:write.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string |
Request body application/json required
| Field | Type | Description |
|---|---|---|
approve required | boolean | |
reason required | string |
Responses
- 200 The case.
Request
curl -X POST "$KULPAY_URL/v1/admin/compliance/cases/{id}/approve" \
-H "Authorization: Bearer $KULPAY_KEY" \
-H "Content-Type: application/json" \
-d '{
"approve": true,
"reason": "agreed"
}'
200 Response application/json
{
"account_id": "3KZlyE2fG4hI6jK8lM0nO2pQ4rS",
"created_at": "2026-10-12T09:00:00Z",
"id": "3KZm0Cs1Dt2Eu3Fv4Gw5Hx6Iy7J",
"opened_by": "system:risk",
"rule_id": "structuring",
"source": "risk_rule",
"status": "open",
"subject_id": "3KZlzP9qR1sT3uV5wX7yZ9aB1cD",
"subject_type": "transaction",
"summary": "risk rule structuring fired (review): amount 950 MZN at or above 900"
}
POST /v1/admin/compliance/cases/{id}/decision
Decide a case (maker)
report (with GIFiM's reference of the communication) or no_report, with a justification of at least 10 characters; a second compliance officer approves it (/approve). Requires compliance:write.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string |
Request body application/json required
| Field | Type | Description |
|---|---|---|
decision required | string | One of: report, no_report |
reason required | string | |
reference | string |
Responses
- 202 Prepared.
Request
curl -X POST "$KULPAY_URL/v1/admin/compliance/cases/{id}/decision" \
-H "Authorization: Bearer $KULPAY_KEY" \
-H "Content-Type: application/json" \
-d '{
"decision": "report",
"reason": "structuring below the review threshold over three days",
"reference": "GIFIM-2026-0099"
}'
202 Response application/json
{
"approval_id": "3KZm1Ab2Cd3Ef4Gh5Ij6Kl7Mn8O",
"message": "decision prepared; a second compliance officer must approve it (POST /v1/admin/compliance/cases/{id}/approve)"
}
POST /v1/admin/compliance/cases/{id}/notes
Record a step of the investigation
Requires compliance:write.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string |
Request body application/json required
| Field | Type | Description |
|---|---|---|
text required | string |
Responses
- 200 The case.
Request
curl -X POST "$KULPAY_URL/v1/admin/compliance/cases/{id}/notes" \
-H "Authorization: Bearer $KULPAY_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "called the partner'\''s compliance officer"
}'
200 Response application/json
{
"account_id": "3KZlyE2fG4hI6jK8lM0nO2pQ4rS",
"created_at": "2026-10-12T09:00:00Z",
"id": "3KZm0Cs1Dt2Eu3Fv4Gw5Hx6Iy7J",
"opened_by": "system:risk",
"rule_id": "structuring",
"source": "risk_rule",
"status": "open",
"subject_id": "3KZlzP9qR1sT3uV5wX7yZ9aB1cD",
"subject_type": "transaction",
"summary": "risk rule structuring fired (review): amount 950 MZN at or above 900"
}
KulPay