MENU navbar-image

Introduction

This documentation aims to provide all the information you need to work with our API.

Authenticating requests

This API is not authenticated.

Admin - Beneficiaries

APIs for Admin Beneficiary Management

Get all beneficiaries with filtering

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/beneficiaries?search=John&status=active&per_page=15" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/beneficiaries"
);

const params = {
    "search": "John",
    "status": "active",
    "per_page": "15",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Beneficiaries retrieved successfully",
    "data": {
        "current_page": 1,
        "data": [
            {
                "id": 1,
                "name": "John Doe",
                "email": "[email protected]",
                "phone": "08012345678",
                "nin": "12345678901",
                "account_number": "1234567890",
                "bank_name": "GTBank",
                "status": "active",
                "total_disbursed": "150000.00",
                "disbursements_count": 3,
                "created_at": "2024-01-01T00:00:00.000000Z"
            }
        ],
        "total": 1
    }
}
 

Request      

GET api/admin/beneficiaries

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Query Parameters

search   string  optional  

optional Search by name, phone, email, or NIN. Example: John

status   string  optional  

optional Filter by status (active,inactive,suspended). Example: active

per_page   integer  optional  

optional Number of items per page. Example: 15

Get a specific beneficiary

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/beneficiaries/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/beneficiaries/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Beneficiary retrieved successfully",
    "data": {
        "id": 1,
        "name": "John Doe",
        "email": "[email protected]",
        "phone": "08012345678",
        "nin": "12345678901",
        "account_number": "1234567890",
        "bank_name": "GTBank",
        "bank_code": "058",
        "address": "123 Main Street, Lagos",
        "average_yearly_income": "500000.00",
        "max_qualification": "Bachelor's Degree",
        "occupation": "Teacher",
        "status": "active",
        "total_disbursed": "150000.00",
        "disbursements": [
            {
                "id": 1,
                "reference": "DISB_ABC123",
                "amount": "50000.00",
                "status": "successful",
                "created_at": "2024-01-01T00:00:00.000000Z"
            }
        ]
    }
}
 

Request      

GET api/admin/beneficiaries/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the beneficiary. Example: 1

Update beneficiary information

Example request:
curl --request PUT \
    "https://api.sabisave.com/api/admin/beneficiaries/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"name\": \"John Doe\",
    \"email\": \"[email protected]\",
    \"address\": \"123 Main Street, Lagos\",
    \"average_yearly_income\": \"600000\",
    \"max_qualification\": \"Master\'s Degree\",
    \"occupation\": \"Engineer\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/beneficiaries/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "name": "John Doe",
    "email": "[email protected]",
    "address": "123 Main Street, Lagos",
    "average_yearly_income": "600000",
    "max_qualification": "Master's Degree",
    "occupation": "Engineer"
};

fetch(url, {
    method: "PUT",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Beneficiary updated successfully",
    "data": {
        "id": 1,
        "name": "John Doe",
        "email": "[email protected]",
        "phone": "08012345678",
        "status": "active"
    }
}
 

Request      

PUT api/admin/beneficiaries/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the beneficiary. Example: 1

Body Parameters

name   string  optional  

optional The full name. Example: John Doe

email   string  optional  

optional The email address. Example: [email protected]

address   string  optional  

optional The address. Example: 123 Main Street, Lagos

average_yearly_income   numeric  optional  

optional Average yearly income. Example: 600000

max_qualification   string  optional  

optional Highest qualification. Example: Master's Degree

occupation   string  optional  

optional Occupation. Example: Engineer

Update beneficiary status

Example request:
curl --request PUT \
    "https://api.sabisave.com/api/admin/beneficiaries/1/status" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"status\": \"suspended\",
    \"reason\": \"Account verification required\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/beneficiaries/1/status"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "status": "suspended",
    "reason": "Account verification required"
};

fetch(url, {
    method: "PUT",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Beneficiary status updated successfully",
    "data": {
        "id": 1,
        "name": "John Doe",
        "status": "suspended"
    }
}
 

Request      

PUT api/admin/beneficiaries/{id}/status

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the beneficiary. Example: 1

Body Parameters

status   string   

The new status (active,inactive,suspended). Example: suspended

reason   string  optional  

optional Reason for status change. Example: Account verification required

Delete a beneficiary

Example request:
curl --request DELETE \
    "https://api.sabisave.com/api/admin/beneficiaries/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/beneficiaries/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "DELETE",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Beneficiary deleted successfully"
}
 

Request      

DELETE api/admin/beneficiaries/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the beneficiary. Example: 1

Get beneficiary analytics

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/beneficiaries/analytics/overview" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/beneficiaries/analytics/overview"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Analytics retrieved successfully",
    "data": {
        "total_beneficiaries": 150,
        "active_beneficiaries": 140,
        "inactive_beneficiaries": 5,
        "suspended_beneficiaries": 5,
        "verified_beneficiaries": 130,
        "total_disbursed": "5000000.00",
        "average_income": "450000.00",
        "monthly_registrations": [
            {
                "month": "2024-01",
                "count": 25
            }
        ]
    }
}
 

Request      

GET api/admin/beneficiaries/analytics/overview

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Admin - Disbursements

APIs for Admin Disbursement Management

Get all disbursements with filtering

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/disbursements?search=John&status=successful&beneficiary_id=1&start_date=2024-01-01&end_date=2024-12-31&per_page=15" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/disbursements"
);

const params = {
    "search": "John",
    "status": "successful",
    "beneficiary_id": "1",
    "start_date": "2024-01-01",
    "end_date": "2024-12-31",
    "per_page": "15",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Disbursements retrieved successfully",
    "data": {
        "current_page": 1,
        "data": [
            {
                "id": 1,
                "reference": "DISB_ABC123",
                "amount": "50000.00",
                "status": "successful",
                "beneficiary": {
                    "id": 1,
                    "name": "John Doe",
                    "phone": "08012345678"
                },
                "processed_by": {
                    "id": 1,
                    "name": "Admin User"
                },
                "created_at": "2024-01-01T00:00:00.000000Z"
            }
        ],
        "total": 1
    }
}
 

Request      

GET api/admin/disbursements

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Query Parameters

search   string  optional  

optional Search by beneficiary name, phone, or reference. Example: John

status   string  optional  

optional Filter by status (pending,processing,successful,failed,cancelled). Example: successful

beneficiary_id   integer  optional  

optional Filter by beneficiary ID. Example: 1

start_date   string  optional  

optional Filter by start date (Y-m-d). Example: 2024-01-01

end_date   string  optional  

optional Filter by end date (Y-m-d). Example: 2024-12-31

per_page   integer  optional  

optional Number of items per page. Example: 15

Get a specific disbursement

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/disbursements/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/disbursements/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Disbursement retrieved successfully",
    "data": {
        "id": 1,
        "reference": "DISB_ABC123",
        "amount": "50000.00",
        "purpose": "Emergency Relief",
        "description": "Emergency fund disbursement",
        "status": "successful",
        "payment_reference": "PAY_123456",
        "processed_at": "2024-01-01T12:00:00.000000Z",
        "beneficiary": {
            "id": 1,
            "name": "John Doe",
            "phone": "08012345678",
            "account_number": "1234567890",
            "bank_name": "GTBank"
        },
        "processed_by": {
            "id": 1,
            "name": "Admin User"
        }
    }
}
 

Request      

GET api/admin/disbursements/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the disbursement. Example: 1

Create a new disbursement

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/disbursements" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"beneficiary_id\": 1,
    \"amount\": \"50000\",
    \"purpose\": \"Emergency Relief\",
    \"description\": \"Emergency fund for medical expenses\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/disbursements"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "beneficiary_id": 1,
    "amount": "50000",
    "purpose": "Emergency Relief",
    "description": "Emergency fund for medical expenses"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (201):


{
    "message": "Disbursement created successfully",
    "data": {
        "id": 1,
        "reference": "DISB_ABC123",
        "amount": "50000.00",
        "purpose": "Emergency Relief",
        "status": "pending",
        "beneficiary": {
            "id": 1,
            "name": "John Doe",
            "phone": "08012345678"
        }
    }
}
 

Request      

POST api/admin/disbursements

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

beneficiary_id   integer   

The ID of the beneficiary. Example: 1

amount   numeric   

The amount to disburse. Example: 50000

purpose   string  optional  

optional The purpose of disbursement. Example: Emergency Relief

description   string  optional  

optional Additional description. Example: Emergency fund for medical expenses

Process a disbursement

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/disbursements/1/process" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/disbursements/1/process"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Disbursement processed successfully",
    "data": {
        "id": 1,
        "reference": "DISB_ABC123",
        "amount": "50000.00",
        "status": "successful",
        "payment_reference": "PAY_123456",
        "processed_at": "2024-01-01T12:00:00.000000Z"
    }
}
 

Request      

POST api/admin/disbursements/{id}/process

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the disbursement. Example: 1

Cancel a disbursement

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/disbursements/1/cancel" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"reason\": \"Beneficiary request\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/disbursements/1/cancel"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "reason": "Beneficiary request"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Disbursement cancelled successfully"
}
 

Request      

POST api/admin/disbursements/{id}/cancel

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the disbursement. Example: 1

Body Parameters

reason   string  optional  

optional Reason for cancellation. Example: Beneficiary request

Get disbursement analytics

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/disbursements/analytics/overview" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/disbursements/analytics/overview"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Analytics retrieved successfully",
    "data": {
        "total_disbursements": 150,
        "total_amount": "5000000.00",
        "successful_disbursements": 140,
        "successful_amount": "4800000.00",
        "pending_disbursements": 5,
        "failed_disbursements": 5,
        "monthly_stats": [
            {
                "month": "2024-01",
                "count": 25,
                "amount": "1000000.00"
            }
        ]
    }
}
 

Request      

GET api/admin/disbursements/analytics/overview

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Admin Authentication

Admin login

Authenticates an admin user and returns an access token. If two-factor authentication is enabled, it will require verification.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/login" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"email\": \"[email protected]\",
    \"password\": \"password123\",
    \"two_factor_code\": \"123456\",
    \"recovery_code\": \"ABCDEF-123456\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/login"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "email": "[email protected]",
    "password": "password123",
    "two_factor_code": "123456",
    "recovery_code": "ABCDEF-123456"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200, Success):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Successfully logged in",
    "data": {
        "token": "1|abcdefghijklmnopqrstuvwxyz123456",
        "refresh_token": "abcdefghijklmnopqrstuvwxyz123456",
        "expire_at": "01-01-23 12:30:00",
        "token_type": "Bearer",
        "admin": {
            "id": 1,
            "name": "Admin User",
            "email": "[email protected]",
            "role": "super_admin",
            "roles": [
                "super_admin"
            ],
            "permissions": [
                "view_dashboard",
                "manage_users"
            ],
            "profile_image": "https://example.com/images/profile.jpg",
            "two_factor_enabled": true,
            "two_factor_method": "email"
        }
    }
}
 

Example response (200, Two-factor required):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Two-factor authentication required",
    "data": {
        "two_factor_required": true,
        "two_factor_method": "email"
    }
}
 

Example response (403, Account deactivated):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Your account has been deactivated. Please contact support.",
    "data": null
}
 

Example response (422, Invalid credentials):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "invalid credentials",
    "data": null
}
 

Request      

POST api/admin/login

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

email   string   

Admin email address. Example: [email protected]

password   string   

Admin password (min 6 characters). Example: password123

two_factor_code   string  optional  

Two-factor authentication code (6 digits). Example: 123456

recovery_code   string  optional  

Recovery code for two-factor authentication. Example: ABCDEF-123456

Admin logout

requires authentication

Invalidates the current access token for the authenticated admin user.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/logout" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/logout"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Successfully logged out",
    "data": null
}
 

Example response (500):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Internal server error",
    "data": null
}
 

Request      

POST api/admin/logout

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Request password reset

Sends a password reset OTP to the admin's email address.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/forgot-password" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"email\": \"[email protected]\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/forgot-password"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "email": "[email protected]"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200, Success):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Password reset OTP sent to your email",
    "data": null
}
 

Example response (404, Email not found):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Admin with this email not found",
    "data": null
}
 

Request      

POST api/admin/forgot-password

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

email   string   

Admin email address. Example: [email protected]

Resend the verification token to the admin's phone number.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/resend-token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"phone\": \"2348012345678\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/resend-token"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "phone": "2348012345678"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "success": true,
    "message": "Verification code resent successfully",
    "data": [],
    "meta-links": []
}
 

Example response (404):


{
    "success": false,
    "message": "Agent not found",
    "errors": []
}
 

Example response (500):


{
    "success": false,
    "message": "Failed to resend verification code",
    "errors": []
}
 

Request      

POST api/admin/resend-token

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

phone   or  optional  

id string required The ID of the agent. Example: 2348012345678

Verify OTP and reset password

Verifies the OTP and resets the admin's password.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/reset-password" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"email\": \"[email protected]\",
    \"otp\": \"123456\",
    \"password\": \"newpassword123\",
    \"password_confirmation\": \"newpassword123\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/reset-password"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "email": "[email protected]",
    "otp": "123456",
    "password": "newpassword123",
    "password_confirmation": "newpassword123"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200, Success):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Password reset successfully",
    "data": null
}
 

Example response (400, Invalid OTP):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Invalid verification code",
    "data": null
}
 

Example response (404, Email not found):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Admin with this email not found",
    "data": null
}
 

Request      

POST api/admin/reset-password

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

email   string   

Admin email address. Example: [email protected]

otp   string   

The verification code sent to the admin's email. Example: 123456

password   string   

New password (min 6 characters). Example: newpassword123

password_confirmation   string   

Password confirmation. Example: newpassword123

Admin Chat

List conversations

requires authentication

Retrieves all chat conversations for the authenticated admin user.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/chat/conversations" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/chat/conversations"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Conversations retrieved successfully",
    "data": [
        {
            "id": 1,
            "title": "Support Conversation",
            "admin_id": 1,
            "agent_id": 2,
            "is_closed": false,
            "last_message": "How can I help you today?",
            "last_message_at": "2023-01-01T12:00:00.000000Z",
            "unread_count": 0,
            "created_at": "2023-01-01T12:00:00.000000Z",
            "updated_at": "2023-01-01T12:00:00.000000Z",
            "agent": {
                "id": 2,
                "first_name": "John",
                "last_name": "Doe",
                "profile": "profiles/agent.jpg"
            }
        }
    ]
}
 

Request      

GET api/admin/chat/conversations

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Get conversation details

requires authentication

Retrieves details of a specific conversation by ID.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/chat/conversations/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/chat/conversations/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Conversation retrieved successfully",
    "data": {
        "id": 1,
        "title": "Support Conversation",
        "admin_id": 1,
        "agent_id": 2,
        "is_closed": false,
        "last_message": "How can I help you today?",
        "last_message_at": "2023-01-01T12:00:00.000000Z",
        "created_at": "2023-01-01T12:00:00.000000Z",
        "updated_at": "2023-01-01T12:00:00.000000Z",
        "agent": {
            "id": 2,
            "first_name": "John",
            "last_name": "Doe",
            "email": "[email protected]",
            "phone": "+1234567890",
            "profile": "profiles/agent.jpg"
        }
    }
}
 

Example response (403):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "You do not have access to this conversation",
    "data": null
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Conversation not found",
    "data": null
}
 

Request      

GET api/admin/chat/conversations/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the conversation. Example: 1

List conversation messages

requires authentication

Retrieves messages for a specific conversation with pagination support. Also marks messages as read for the authenticated admin.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/chat/conversations/neque/messages?page=1&per_page=15" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/chat/conversations/neque/messages"
);

const params = {
    "page": "1",
    "per_page": "15",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Messages retrieved successfully",
    "data": {
        "current_page": 1,
        "data": [
            {
                "id": 1,
                "conversation_id": 1,
                "sender_type": "App\\Models\\Admin",
                "sender_id": 1,
                "message": "Hello, how can I help you today?",
                "attachments": [],
                "is_read": true,
                "created_at": "2023-01-01T12:00:00.000000Z",
                "updated_at": "2023-01-01T12:00:00.000000Z",
                "sender": {
                    "id": 1,
                    "name": "Admin User",
                    "profile_image": "profiles/admin.jpg"
                }
            },
            {
                "id": 2,
                "conversation_id": 1,
                "sender_type": "App\\Models\\Agent",
                "sender_id": 2,
                "message": "I need help with my account",
                "attachments": [],
                "is_read": true,
                "created_at": "2023-01-01T12:05:00.000000Z",
                "updated_at": "2023-01-01T12:05:00.000000Z",
                "sender": {
                    "id": 2,
                    "first_name": "John",
                    "last_name": "Doe",
                    "profile": "profiles/agent.jpg"
                }
            }
        ],
        "first_page_url": "http://example.com/api/admin/chat/conversations/1/messages?page=1",
        "from": 1,
        "last_page": 1,
        "last_page_url": "http://example.com/api/admin/chat/conversations/1/messages?page=1",
        "links": [],
        "next_page_url": null,
        "path": "http://example.com/api/admin/chat/conversations/1/messages",
        "per_page": 15,
        "prev_page_url": null,
        "to": 2,
        "total": 2
    }
}
 

Example response (403):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "You do not have access to this conversation",
    "data": null
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Conversation not found",
    "data": null
}
 

Request      

GET api/admin/chat/conversations/{id}/messages

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the conversation. Example: neque

conversationId   integer   

The ID of the conversation. Example: 1

Query Parameters

page   integer  optional  

Page number for pagination. Example: 1

per_page   integer  optional  

Number of messages per page. Example: 15

Create conversation

requires authentication

Creates a new chat conversation between the authenticated admin and an agent.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/chat/conversations" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"agent_id\": 2,
    \"title\": \"Support Request\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/chat/conversations"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "agent_id": 2,
    "title": "Support Request"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Conversation created successfully",
    "data": {
        "id": 1,
        "title": "Support Request",
        "admin_id": 1,
        "agent_id": 2,
        "is_closed": false,
        "created_at": "2023-01-01T12:00:00.000000Z",
        "updated_at": "2023-01-01T12:00:00.000000Z",
        "agent": {
            "id": 2,
            "first_name": "John",
            "last_name": "Doe",
            "email": "[email protected]",
            "phone": "+1234567890",
            "profile": "profiles/agent.jpg"
        }
    }
}
 

Example response (422):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "The agent id field is required",
    "data": null
}
 

Request      

POST api/admin/chat/conversations

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

agent_id   integer   

The ID of the agent to start a conversation with. Example: 2

title   string  optional  

Optional title for the conversation. Example: Support Request

Send message

requires authentication

Sends a new message in an existing conversation.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/chat/conversations/iste/messages" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"message\": \"Hello, how can I help you today?\",
    \"attachments\": [
        \"distinctio\"
    ]
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/chat/conversations/iste/messages"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "message": "Hello, how can I help you today?",
    "attachments": [
        "distinctio"
    ]
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Message sent successfully",
    "data": {
        "id": 3,
        "conversation_id": 1,
        "sender_type": "App\\Models\\Admin",
        "sender_id": 1,
        "message": "Hello, how can I help you today?",
        "attachments": [],
        "is_read": false,
        "created_at": "2023-01-01T12:10:00.000000Z",
        "updated_at": "2023-01-01T12:10:00.000000Z",
        "sender": {
            "id": 1,
            "name": "Admin User",
            "profile_image": "profiles/admin.jpg"
        }
    }
}
 

Example response (400):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "This conversation is closed",
    "data": null
}
 

Example response (403):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "You do not have access to this conversation",
    "data": null
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Conversation not found",
    "data": null
}
 

Example response (422):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "The message field is required",
    "data": null
}
 

Request      

POST api/admin/chat/conversations/{id}/messages

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the conversation. Example: iste

conversationId   integer   

The ID of the conversation. Example: 1

Body Parameters

message   string   

The message content to send. Example: Hello, how can I help you today?

attachments   string[]  optional  

Optional array of attachments to include with the message.

Close conversation

requires authentication

Closes an active conversation, preventing new messages from being sent.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/chat/conversations/consectetur/close" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/chat/conversations/consectetur/close"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Conversation closed successfully",
    "data": null
}
 

Example response (403):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "You do not have access to this conversation",
    "data": null
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Conversation not found",
    "data": null
}
 

Request      

POST api/admin/chat/conversations/{id}/close

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the conversation. Example: consectetur

conversationId   integer   

The ID of the conversation to close. Example: 1

Reopen conversation

requires authentication

Reopens a previously closed conversation, allowing new messages to be sent.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/chat/conversations/eligendi/reopen" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/chat/conversations/eligendi/reopen"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Conversation reopened successfully",
    "data": null
}
 

Example response (403):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "You do not have access to this conversation",
    "data": null
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Conversation not found",
    "data": null
}
 

Request      

POST api/admin/chat/conversations/{id}/reopen

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the conversation. Example: eligendi

conversationId   integer   

The ID of the conversation to reopen. Example: 1

List available agents

requires authentication

Retrieves a list of all agents available for starting a new conversation.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/chat/agents" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/chat/agents"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Agents retrieved successfully",
    "data": [
        {
            "id": 1,
            "first_name": "John",
            "last_name": "Doe",
            "email": "[email protected]",
            "phone": "+1234567890",
            "profile": "profiles/agent1.jpg"
        },
        {
            "id": 2,
            "first_name": "Jane",
            "last_name": "Smith",
            "email": "[email protected]",
            "phone": "+0987654321",
            "profile": "profiles/agent2.jpg"
        }
    ]
}
 

Request      

GET api/admin/chat/agents

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Admin Dashboard

APIs for retrieving dashboard statistics and analytics data

Get Dashboard Statistics

requires authentication

Retrieves comprehensive dashboard statistics and analytics data for the admin dashboard, including financial summaries, user counts, and chart data for visualizations.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/dashboard?time_frame=last_30_days&chart_period=yearly" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/dashboard"
);

const params = {
    "time_frame": "last_30_days",
    "chart_period": "yearly",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200, Success):


{
    "success": true,
    "message": "Dashboard data retrieved successfully",
    "data": {
        "summary": {
            "total_collections": 250000.5,
            "total_withdrawals": 125000.25,
            "total_traders": 500,
            "total_agents": 50
        },
        "analytics": {
            "labels": [
                "Jan",
                "Feb",
                "Mar",
                "Apr",
                "May",
                "Jun",
                "Jul",
                "Aug",
                "Sep",
                "Oct",
                "Nov",
                "Dec"
            ],
            "datasets": [
                {
                    "label": "Collections",
                    "data": [
                        15000,
                        21000,
                        18000,
                        24000,
                        23000,
                        24000,
                        19000,
                        20000,
                        22000,
                        20000,
                        25000,
                        19000
                    ],
                    "borderColor": "#F6C000",
                    "backgroundColor": "rgba(246, 192, 0, 0.1)"
                },
                {
                    "label": "Withdrawals",
                    "data": [
                        10000,
                        15000,
                        12000,
                        14000,
                        9000,
                        10000,
                        12000,
                        8000,
                        7500,
                        9000,
                        10000,
                        8500
                    ],
                    "borderColor": "#000000",
                    "backgroundColor": "rgba(0, 0, 0, 0.1)"
                }
            ]
        },
        "time_frame": "last_30_days"
    }
}
 

Example response (500, Server Error):


{
    "success": false,
    "message": "Internal server error",
    "error": {
        "code": 500,
        "message": "Server error details"
    }
}
 

Request      

GET api/admin/dashboard

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Query Parameters

time_frame   string  optional  

optional The time period for which to retrieve statistics. Options: today, yesterday, last_30_days (default). Example: last_30_days

chart_period   string  optional  

optional The period for chart data. Options: yearly (default). Example: yearly

Admin Management

List all admins

requires authentication

Retrieves a paginated list of all admin users with optional filtering by name, email, role, or status.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/admins?search=john&role=editor&status=1&page=1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/admins"
);

const params = {
    "search": "john",
    "role": "editor",
    "status": "1",
    "page": "1",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Admins retrieved successfully",
    "data": {
        "admins": {
            "current_page": 1,
            "data": [
                {
                    "id": 1,
                    "name": "Admin User",
                    "email": "[email protected]",
                    "phone": "1234567890",
                    "profile_image": "admin-profiles/image.jpg",
                    "status": true,
                    "created_at": "2023-01-01T12:00:00.000000Z",
                    "updated_at": "2023-01-01T12:00:00.000000Z",
                    "roles": [
                        {
                            "id": 1,
                            "name": "super-admin",
                            "guard_name": "admin",
                            "description": "Super Administrator",
                            "created_at": "2023-01-01T12:00:00.000000Z",
                            "updated_at": "2023-01-01T12:00:00.000000Z"
                        }
                    ]
                }
            ],
            "first_page_url": "http://example.com/api/admin/admins?page=1",
            "from": 1,
            "last_page": 1,
            "last_page_url": "http://example.com/api/admin/admins?page=1",
            "links": [],
            "next_page_url": null,
            "path": "http://example.com/api/admin/admins",
            "per_page": 10,
            "prev_page_url": null,
            "to": 1,
            "total": 1
        },
        "roles": [
            {
                "id": 1,
                "name": "super-admin",
                "guard_name": "admin",
                "description": "Super Administrator",
                "created_at": "2023-01-01T12:00:00.000000Z",
                "updated_at": "2023-01-01T12:00:00.000000Z"
            }
        ]
    }
}
 

Request      

GET api/admin/admins

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Query Parameters

search   string  optional  

Search term for filtering by name or email. Example: john

role   string  optional  

Filter by role name. Example: editor

status   boolean  optional  

Filter by account status (1 for active, 0 for inactive). Example: true

page   integer  optional  

Page number for pagination. Example: 1

Get admin details

requires authentication

Retrieves detailed information about a specific admin user including their roles.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/admins/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/admins/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Admin retrieved successfully",
    "data": {
        "id": 1,
        "name": "Admin",
        "last_name": "User",
        "email": "[email protected]",
        "phone": "+1234567890",
        "profile_image": "admin-profiles/profile.jpg",
        "status": true,
        "is_admin": true,
        "gender": "male",
        "dob": "1990-01-01",
        "address": "123 Main St, City",
        "created_at": "2023-01-01T12:00:00.000000Z",
        "updated_at": "2023-01-01T12:00:00.000000Z",
        "roles": [
            {
                "id": 1,
                "name": "super-admin",
                "guard_name": "admin",
                "description": "Super Administrator",
                "created_at": "2023-01-01T12:00:00.000000Z",
                "updated_at": "2023-01-01T12:00:00.000000Z"
            }
        ]
    }
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Admin not found",
    "data": null
}
 

Request      

GET api/admin/admins/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the admin. Example: 1

Create a new admin

requires authentication

Creates a new admin user with the specified details and assigns a role.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/admins/store" \
    --header "Content-Type: multipart/form-data" \
    --header "Accept: application/json" \
    --form "name=John"\
    --form "[email protected]"\
    --form "password=password123"\
    --form "role=editor"\
    --form "phone=+1234567890"\
    --form "last_name=Doe"\
    --form "gender=male"\
    --form "dob=1990-01-01"\
    --form "address=123 Main St, City"\
    --form "profile_image=@/tmp/php09cRr0" 
const url = new URL(
    "https://api.sabisave.com/api/admin/admins/store"
);

const headers = {
    "Content-Type": "multipart/form-data",
    "Accept": "application/json",
};

const body = new FormData();
body.append('name', 'John');
body.append('email', '[email protected]');
body.append('password', 'password123');
body.append('role', 'editor');
body.append('phone', '+1234567890');
body.append('last_name', 'Doe');
body.append('gender', 'male');
body.append('dob', '1990-01-01');
body.append('address', '123 Main St, City');
body.append('profile_image', document.querySelector('input[name="profile_image"]').files[0]);

fetch(url, {
    method: "POST",
    headers,
    body,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Admin created successfully",
    "data": {
        "id": 2,
        "name": "John",
        "last_name": "Doe",
        "email": "[email protected]",
        "phone": "+1234567890",
        "profile_image": "admin-profiles/profile.jpg",
        "status": true,
        "is_admin": true,
        "gender": "male",
        "dob": "1990-01-01",
        "address": "123 Main St, City",
        "created_at": "2023-01-01T12:00:00.000000Z",
        "updated_at": "2023-01-01T12:00:00.000000Z"
    }
}
 

Example response (422):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "The given data was invalid.",
    "data": {
        "email": [
            "The email has already been taken."
        ]
    }
}
 

Request      

POST api/admin/admins/store

Headers

Content-Type      

Example: multipart/form-data

Accept      

Example: application/json

Body Parameters

name   string   

Admin's first name. Example: John

email   string   

Admin's email address. Example: [email protected]

password   string   

Admin's password (min 8 characters). Example: password123

role   string   

Role name to assign to the admin. Example: editor

phone   string  optional  

Admin's phone number. Example: +1234567890

profile_image   file  optional  

Admin's profile image (jpeg, png, jpg, gif, max 2MB). Example: /tmp/php09cRr0

last_name   string  optional  

Admin's last name. Example: Doe

gender   string  optional  

Admin's gender (male, female, rather_not_say). Example: male

dob   date  optional  

Admin's date of birth. Example: 1990-01-01

address   string  optional  

Admin's address. Example: 123 Main St, City

Update admin

requires authentication

Updates an existing admin user's details and role.

Example request:
curl --request PUT \
    "https://api.sabisave.com/api/admin/admins/update/1" \
    --header "Content-Type: multipart/form-data" \
    --header "Accept: application/json" \
    --form "name=John"\
    --form "[email protected]"\
    --form "role=editor"\
    --form "phone=+1234567890"\
    --form "last_name=Doe"\
    --form "gender=male"\
    --form "dob=1990-01-01"\
    --form "password=newpassword123"\
    --form "address=123 Main St, City"\
    --form "profile_image=@/tmp/phpBcyRHK" 
const url = new URL(
    "https://api.sabisave.com/api/admin/admins/update/1"
);

const headers = {
    "Content-Type": "multipart/form-data",
    "Accept": "application/json",
};

const body = new FormData();
body.append('name', 'John');
body.append('email', '[email protected]');
body.append('role', 'editor');
body.append('phone', '+1234567890');
body.append('last_name', 'Doe');
body.append('gender', 'male');
body.append('dob', '1990-01-01');
body.append('password', 'newpassword123');
body.append('address', '123 Main St, City');
body.append('profile_image', document.querySelector('input[name="profile_image"]').files[0]);

fetch(url, {
    method: "PUT",
    headers,
    body,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Admin updated successfully",
    "data": {
        "id": 1,
        "name": "John",
        "last_name": "Doe",
        "email": "[email protected]",
        "phone": "+1234567890",
        "profile_image": "admin-profiles/profile.jpg",
        "status": true,
        "is_admin": true,
        "gender": "male",
        "dob": "1990-01-01",
        "address": "123 Main St, City",
        "created_at": "2023-01-01T12:00:00.000000Z",
        "updated_at": "2023-01-01T12:00:00.000000Z"
    }
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Admin not found",
    "data": null
}
 

Example response (422):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "The given data was invalid.",
    "data": {
        "email": [
            "The email has already been taken."
        ]
    }
}
 

Request      

PUT api/admin/admins/update/{id}

Headers

Content-Type      

Example: multipart/form-data

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the admin. Example: 1

Body Parameters

name   string   

Admin's first name. Example: John

email   string   

Admin's email address. Example: [email protected]

role   string   

Role name to assign to the admin. Example: editor

phone   string  optional  

Admin's phone number. Example: +1234567890

profile_image   file  optional  

Admin's profile image (jpeg, png, jpg, gif, max 2MB). Example: /tmp/phpBcyRHK

last_name   string  optional  

Admin's last name. Example: Doe

gender   string  optional  

Admin's gender (male, female, rather_not_say). Example: male

dob   date  optional  

Admin's date of birth. Example: 1990-01-01

password   string  optional  

Admin's new password (min 8 characters). Example: newpassword123

address   string  optional  

Admin's address. Example: 123 Main St, City

Delete admin

requires authentication

Permanently deletes an admin account.

Example request:
curl --request DELETE \
    "https://api.sabisave.com/api/admin/admins/delete/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/admins/delete/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "DELETE",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Admin deleted successfully",
    "data": null
}
 

Example response (403):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Cannot delete your own account",
    "data": null
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Admin not found",
    "data": null
}
 

Request      

DELETE api/admin/admins/delete/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the admin. Example: 1

Toggle admin status

requires authentication

Activates or deactivates an admin account.

Example request:
curl --request PATCH \
    "https://api.sabisave.com/api/admin/admins/toggle-status/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/admins/toggle-status/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "PATCH",
    headers,
}).then(response => response.json());

Example response (200, Deactivated):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Admin deactivated successfully",
    "data": {
        "id": 1,
        "status": false,
        "updated_at": "2023-01-01T12:00:00.000000Z"
    }
}
 

Example response (200, Activated):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Admin activated successfully",
    "data": {
        "id": 1,
        "status": true,
        "updated_at": "2023-01-01T12:00:00.000000Z"
    }
}
 

Example response (403):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Cannot deactivate your own account",
    "data": null
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Admin not found",
    "data": null
}
 

Request      

PATCH api/admin/admins/toggle-status/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the admin. Example: 1

Create a new admin

requires authentication

Creates a new admin user with the specified details and assigns a role.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/admins" \
    --header "Content-Type: multipart/form-data" \
    --header "Accept: application/json" \
    --form "name=John"\
    --form "[email protected]"\
    --form "password=password123"\
    --form "role=editor"\
    --form "phone=+1234567890"\
    --form "last_name=Doe"\
    --form "gender=male"\
    --form "dob=1990-01-01"\
    --form "address=123 Main St, City"\
    --form "profile_image=@/tmp/php6BKF4Z" 
const url = new URL(
    "https://api.sabisave.com/api/admin/admins"
);

const headers = {
    "Content-Type": "multipart/form-data",
    "Accept": "application/json",
};

const body = new FormData();
body.append('name', 'John');
body.append('email', '[email protected]');
body.append('password', 'password123');
body.append('role', 'editor');
body.append('phone', '+1234567890');
body.append('last_name', 'Doe');
body.append('gender', 'male');
body.append('dob', '1990-01-01');
body.append('address', '123 Main St, City');
body.append('profile_image', document.querySelector('input[name="profile_image"]').files[0]);

fetch(url, {
    method: "POST",
    headers,
    body,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Admin created successfully",
    "data": {
        "id": 2,
        "name": "John",
        "last_name": "Doe",
        "email": "[email protected]",
        "phone": "+1234567890",
        "profile_image": "admin-profiles/profile.jpg",
        "status": true,
        "is_admin": true,
        "gender": "male",
        "dob": "1990-01-01",
        "address": "123 Main St, City",
        "created_at": "2023-01-01T12:00:00.000000Z",
        "updated_at": "2023-01-01T12:00:00.000000Z"
    }
}
 

Example response (422):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "The given data was invalid.",
    "data": {
        "email": [
            "The email has already been taken."
        ]
    }
}
 

Request      

POST api/admin/admins

Headers

Content-Type      

Example: multipart/form-data

Accept      

Example: application/json

Body Parameters

name   string   

Admin's first name. Example: John

email   string   

Admin's email address. Example: [email protected]

password   string   

Admin's password (min 8 characters). Example: password123

role   string   

Role name to assign to the admin. Example: editor

phone   string  optional  

Admin's phone number. Example: +1234567890

profile_image   file  optional  

Admin's profile image (jpeg, png, jpg, gif, max 2MB). Example: /tmp/php6BKF4Z

last_name   string  optional  

Admin's last name. Example: Doe

gender   string  optional  

Admin's gender (male, female, rather_not_say). Example: male

dob   date  optional  

Admin's date of birth. Example: 1990-01-01

address   string  optional  

Admin's address. Example: 123 Main St, City

Update admin

requires authentication

Updates an existing admin user's details and role.

Example request:
curl --request PUT \
    "https://api.sabisave.com/api/admin/admins/1" \
    --header "Content-Type: multipart/form-data" \
    --header "Accept: application/json" \
    --form "name=John"\
    --form "[email protected]"\
    --form "role=editor"\
    --form "phone=+1234567890"\
    --form "last_name=Doe"\
    --form "gender=male"\
    --form "dob=1990-01-01"\
    --form "password=newpassword123"\
    --form "address=123 Main St, City"\
    --form "profile_image=@/tmp/phpNmtVce" 
const url = new URL(
    "https://api.sabisave.com/api/admin/admins/1"
);

const headers = {
    "Content-Type": "multipart/form-data",
    "Accept": "application/json",
};

const body = new FormData();
body.append('name', 'John');
body.append('email', '[email protected]');
body.append('role', 'editor');
body.append('phone', '+1234567890');
body.append('last_name', 'Doe');
body.append('gender', 'male');
body.append('dob', '1990-01-01');
body.append('password', 'newpassword123');
body.append('address', '123 Main St, City');
body.append('profile_image', document.querySelector('input[name="profile_image"]').files[0]);

fetch(url, {
    method: "PUT",
    headers,
    body,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Admin updated successfully",
    "data": {
        "id": 1,
        "name": "John",
        "last_name": "Doe",
        "email": "[email protected]",
        "phone": "+1234567890",
        "profile_image": "admin-profiles/profile.jpg",
        "status": true,
        "is_admin": true,
        "gender": "male",
        "dob": "1990-01-01",
        "address": "123 Main St, City",
        "created_at": "2023-01-01T12:00:00.000000Z",
        "updated_at": "2023-01-01T12:00:00.000000Z"
    }
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Admin not found",
    "data": null
}
 

Example response (422):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "The given data was invalid.",
    "data": {
        "email": [
            "The email has already been taken."
        ]
    }
}
 

Request      

PUT api/admin/admins/{id}

Headers

Content-Type      

Example: multipart/form-data

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the admin. Example: 1

Body Parameters

name   string   

Admin's first name. Example: John

email   string   

Admin's email address. Example: [email protected]

role   string   

Role name to assign to the admin. Example: editor

phone   string  optional  

Admin's phone number. Example: +1234567890

profile_image   file  optional  

Admin's profile image (jpeg, png, jpg, gif, max 2MB). Example: /tmp/phpNmtVce

last_name   string  optional  

Admin's last name. Example: Doe

gender   string  optional  

Admin's gender (male, female, rather_not_say). Example: male

dob   date  optional  

Admin's date of birth. Example: 1990-01-01

password   string  optional  

Admin's new password (min 8 characters). Example: newpassword123

address   string  optional  

Admin's address. Example: 123 Main St, City

Toggle admin status

requires authentication

Activates or deactivates an admin account.

Example request:
curl --request PATCH \
    "https://api.sabisave.com/api/admin/admins/1/toggle-status" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/admins/1/toggle-status"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "PATCH",
    headers,
}).then(response => response.json());

Example response (200, Deactivated):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Admin deactivated successfully",
    "data": {
        "id": 1,
        "status": false,
        "updated_at": "2023-01-01T12:00:00.000000Z"
    }
}
 

Example response (200, Activated):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Admin activated successfully",
    "data": {
        "id": 1,
        "status": true,
        "updated_at": "2023-01-01T12:00:00.000000Z"
    }
}
 

Example response (403):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Cannot deactivate your own account",
    "data": null
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Admin not found",
    "data": null
}
 

Request      

PATCH api/admin/admins/{id}/toggle-status

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the admin. Example: 1

Delete admin

requires authentication

Permanently deletes an admin account.

Example request:
curl --request DELETE \
    "https://api.sabisave.com/api/admin/admins/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/admins/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "DELETE",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Admin deleted successfully",
    "data": null
}
 

Example response (403):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Cannot delete your own account",
    "data": null
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Admin not found",
    "data": null
}
 

Request      

DELETE api/admin/admins/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the admin. Example: 1

Admin Profile Management

APIs for managing admin profile information

Get Admin Profile

requires authentication

Retrieves the authenticated admin's profile information including personal details and last login time.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/profile" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/profile"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200, Success):


{
    "success": true,
    "message": "Profile retrieved successfully",
    "data": {
        "id": 1,
        "name": "John",
        "email": "[email protected]",
        "phone": "+1234567890",
        "role": "super_admin",
        "profile_image": "storage/admin/profile/image.jpg",
        "last_name": "Doe",
        "gender": "male",
        "dob": "1990-01-01",
        "address": "123 Admin Street, City",
        "last_login_at": "2023-05-17 10:30:45"
    }
}
 

Example response (500, Server Error):


{
    "success": false,
    "message": "Internal server error",
    "error": {
        "code": 500,
        "message": "Server error details"
    }
}
 

Request      

GET api/admin/profile

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Update Admin Profile

requires authentication

Updates the authenticated admin's profile information with the provided data.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/profile/update" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"name\": \"John\",
    \"email\": \"[email protected]\",
    \"phone\": \"+1234567890\",
    \"last_name\": \"Doe\",
    \"gender\": \"male\",
    \"dob\": \"1990-01-01\",
    \"address\": \"123 Admin Street, City\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/profile/update"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "name": "John",
    "email": "[email protected]",
    "phone": "+1234567890",
    "last_name": "Doe",
    "gender": "male",
    "dob": "1990-01-01",
    "address": "123 Admin Street, City"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200, Success):


{
    "success": true,
    "message": "Profile updated successfully",
    "data": {
        "id": 1,
        "name": "John",
        "email": "[email protected]",
        "phone": "+1234567890",
        "role": "super_admin",
        "profile_image": "storage/admin/profile/image.jpg",
        "last_name": "Doe",
        "gender": "male",
        "dob": "1990-01-01",
        "address": "123 Admin Street, City"
    }
}
 

Example response (400, Validation Error):


{
    "success": false,
    "message": "Validation failed",
    "error": {
        "code": 400,
        "message": "The email has already been taken.",
        "data": {
            "email": [
                "The email has already been taken."
            ]
        }
    }
}
 

Example response (500, Server Error):


{
    "success": false,
    "message": "Internal server error",
    "error": {
        "code": 500,
        "message": "Server error details"
    }
}
 

Request      

POST api/admin/profile/update

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

name   string  optional  

optional The admin's first name. Example: John

email   string  optional  

optional The admin's email address. Must be unique. Example: [email protected]

phone   string  optional  

optional The admin's phone number. Example: +1234567890

last_name   string  optional  

optional The admin's last name. Example: Doe

gender   string  optional  

optional The admin's gender. Must be one of: male, female, rather_not_say. Example: male

dob   date  optional  

optional The admin's date of birth. Example: 1990-01-01

address   string  optional  

optional The admin's address. Example: 123 Admin Street, City

Update Admin Profile Image

requires authentication

Updates the authenticated admin's profile image.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/profile/update-image" \
    --header "Content-Type: multipart/form-data" \
    --header "Accept: application/json" \
    --form "profile_image=@/tmp/phpBjh8CZ" 
const url = new URL(
    "https://api.sabisave.com/api/admin/profile/update-image"
);

const headers = {
    "Content-Type": "multipart/form-data",
    "Accept": "application/json",
};

const body = new FormData();
body.append('profile_image', document.querySelector('input[name="profile_image"]').files[0]);

fetch(url, {
    method: "POST",
    headers,
    body,
}).then(response => response.json());

Example response (200, Success):


{
    "success": true,
    "message": "Profile image updated successfully",
    "data": {
        "profile_image": "storage/admin/profile/image123456.jpg"
    }
}
 

Example response (400, Validation Error):


{
    "success": false,
    "message": "Validation failed",
    "error": {
        "code": 400,
        "message": "The profile image field is required.",
        "data": {
            "profile_image": [
                "The profile image field is required."
            ]
        }
    }
}
 

Example response (500, Server Error):


{
    "success": false,
    "message": "Internal server error",
    "error": {
        "code": 500,
        "message": "Server error details"
    }
}
 

Request      

POST api/admin/profile/update-image

Headers

Content-Type      

Example: multipart/form-data

Accept      

Example: application/json

Body Parameters

profile_image   file   

The admin's profile image file. Must be an image (jpeg, png, jpg, gif) and less than 2MB. Example: /tmp/phpBjh8CZ

Change Admin Password

requires authentication

Updates the authenticated admin's password after verifying the current password.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/profile/change-password" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"current_password\": null,
    \"password\": null,
    \"password_confirmation\": null
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/profile/change-password"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "current_password": null,
    "password": null,
    "password_confirmation": null
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200, Success):


{
    "success": true,
    "message": "Password changed successfully"
}
 

Example response (400, Validation Error):


{
    "success": false,
    "message": "Validation failed",
    "error": {
        "code": 400,
        "message": "The password confirmation does not match.",
        "data": {
            "password": [
                "The password confirmation does not match."
            ]
        }
    }
}
 

Example response (400, Incorrect Current Password):


{
    "success": false,
    "message": "Current password is incorrect",
    "error": {
        "code": 102,
        "message": "Current password is incorrect"
    }
}
 

Example response (500, Server Error):


{
    "success": false,
    "message": "Internal server error",
    "error": {
        "code": 500,
        "message": "Server error details"
    }
}
 

Request      

POST api/admin/profile/change-password

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

current_password   string   

The admin's current password.

password   string   

The new password. Must be at least 8 characters.

password_confirmation   string   

Must match the new password.

Admin Roles & Permissions

List all roles

requires authentication

Retrieves a list of all available admin roles.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/admins/roles" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/admins/roles"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Roles retrieved successfully",
    "data": [
        {
            "id": 1,
            "name": "super-admin",
            "guard_name": "admin",
            "description": "Super Administrator",
            "created_at": "2023-01-01T12:00:00.000000Z",
            "updated_at": "2023-01-01T12:00:00.000000Z",
            "permissions": [
                {
                    "id": 1,
                    "name": "manage_admins",
                    "guard_name": "admin",
                    "created_at": "2023-01-01T12:00:00.000000Z",
                    "updated_at": "2023-01-01T12:00:00.000000Z"
                }
            ]
        }
    ]
}
 

Request      

GET api/admin/admins/roles

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

List all roles

requires authentication

Retrieves a list of all available admin roles.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/roles" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/roles"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Roles retrieved successfully",
    "data": [
        {
            "id": 1,
            "name": "super-admin",
            "guard_name": "admin",
            "description": "Super Administrator",
            "created_at": "2023-01-01T12:00:00.000000Z",
            "updated_at": "2023-01-01T12:00:00.000000Z",
            "permissions": [
                {
                    "id": 1,
                    "name": "manage_admins",
                    "guard_name": "admin",
                    "created_at": "2023-01-01T12:00:00.000000Z",
                    "updated_at": "2023-01-01T12:00:00.000000Z"
                }
            ]
        }
    ]
}
 

Request      

GET api/admin/roles

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Create role

requires authentication

Creates a new role with assigned permissions.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/roles" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"name\": \"editor\",
    \"permissions\": [
        \"view_dashboard\",
        \"manage_content\"
    ],
    \"description\": \"Content Editor Role\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/roles"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "name": "editor",
    "permissions": [
        "view_dashboard",
        "manage_content"
    ],
    "description": "Content Editor Role"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Role created successfully",
    "data": {
        "id": 2,
        "name": "editor",
        "guard_name": "admin",
        "description": "Content Editor Role",
        "created_at": "2023-01-01T12:00:00.000000Z",
        "updated_at": "2023-01-01T12:00:00.000000Z",
        "permissions": [
            {
                "id": 2,
                "name": "view_dashboard",
                "guard_name": "admin",
                "created_at": "2023-01-01T12:00:00.000000Z",
                "updated_at": "2023-01-01T12:00:00.000000Z"
            },
            {
                "id": 3,
                "name": "manage_content",
                "guard_name": "admin",
                "created_at": "2023-01-01T12:00:00.000000Z",
                "updated_at": "2023-01-01T12:00:00.000000Z"
            }
        ]
    }
}
 

Example response (422):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "The given data was invalid.",
    "data": {
        "name": [
            "The name has already been taken."
        ]
    }
}
 

Request      

POST api/admin/roles

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

name   string   

The name of the role. Example: editor

permissions   string[]   

List of permission names to assign to the role.

description   string  optional  

Description of the role. Example: Content Editor Role

Update role

requires authentication

Updates an existing role and its assigned permissions.

Example request:
curl --request PUT \
    "https://api.sabisave.com/api/admin/roles/2" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"name\": \"content_editor\",
    \"permissions\": [
        \"view_dashboard\",
        \"manage_content\",
        \"publish_articles\"
    ],
    \"description\": \"Content Editor with publishing rights\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/roles/2"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "name": "content_editor",
    "permissions": [
        "view_dashboard",
        "manage_content",
        "publish_articles"
    ],
    "description": "Content Editor with publishing rights"
};

fetch(url, {
    method: "PUT",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Role updated successfully",
    "data": {
        "id": 2,
        "name": "content_editor",
        "guard_name": "admin",
        "description": "Content Editor with publishing rights",
        "created_at": "2023-01-01T12:00:00.000000Z",
        "updated_at": "2023-01-01T12:00:00.000000Z",
        "permissions": [
            {
                "id": 2,
                "name": "view_dashboard",
                "guard_name": "admin",
                "created_at": "2023-01-01T12:00:00.000000Z",
                "updated_at": "2023-01-01T12:00:00.000000Z"
            },
            {
                "id": 3,
                "name": "manage_content",
                "guard_name": "admin",
                "created_at": "2023-01-01T12:00:00.000000Z",
                "updated_at": "2023-01-01T12:00:00.000000Z"
            },
            {
                "id": 4,
                "name": "publish_articles",
                "guard_name": "admin",
                "created_at": "2023-01-01T12:00:00.000000Z",
                "updated_at": "2023-01-01T12:00:00.000000Z"
            }
        ]
    }
}
 

Example response (403):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Cannot modify super-admin role",
    "data": null
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Role not found",
    "data": null
}
 

Request      

PUT api/admin/roles/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the role. Example: 2

Body Parameters

name   string   

The name of the role. Example: content_editor

permissions   string[]   

List of permission names to assign to the role.

description   string  optional  

Description of the role. Example: Content Editor with publishing rights

Delete role

requires authentication

Permanently deletes a role if it's not assigned to any admin users.

Example request:
curl --request DELETE \
    "https://api.sabisave.com/api/admin/roles/2" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/roles/2"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "DELETE",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Role deleted successfully",
    "data": null
}
 

Example response (400):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Cannot delete role that is assigned to 2 admin(s)",
    "data": null
}
 

Example response (403):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Cannot delete super-admin role",
    "data": null
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Role not found",
    "data": null
}
 

Request      

DELETE api/admin/roles/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the role. Example: 2

List all permissions

requires authentication

Retrieves a list of all available permissions for admin roles.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/permissions" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/permissions"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Permissions retrieved successfully",
    "data": [
        {
            "id": 1,
            "name": "manage_admins",
            "guard_name": "admin",
            "created_at": "2023-01-01T12:00:00.000000Z",
            "updated_at": "2023-01-01T12:00:00.000000Z"
        },
        {
            "id": 2,
            "name": "view_dashboard",
            "guard_name": "admin",
            "created_at": "2023-01-01T12:00:00.000000Z",
            "updated_at": "2023-01-01T12:00:00.000000Z"
        }
    ]
}
 

Request      

GET api/admin/permissions

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Admin Two-Factor Authentication

Get 2FA status

requires authentication

Retrieves the current two-factor authentication status for the authenticated admin user.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/two-factor-auth/status" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/two-factor-auth/status"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Two-factor authentication status retrieved successfully",
    "data": {
        "enabled": true,
        "method": "email",
        "confirmed": true,
        "has_recovery_codes": true
    }
}
 

Example response (401):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "User not authenticated",
    "data": null
}
 

Request      

GET api/admin/two-factor-auth/status

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Enable 2FA

requires authentication

Enables two-factor authentication for the authenticated admin user and generates recovery codes.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/two-factor-auth/enable" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"method\": \"email\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/two-factor-auth/enable"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "method": "email"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Two-factor authentication has been enabled",
    "data": {
        "recovery_codes": [
            "ABCDEF-123456",
            "GHIJKL-789012",
            "MNOPQR-345678",
            "STUVWX-901234",
            "YZABCD-567890",
            "EFGHIJ-123456",
            "KLMNOP-789012",
            "QRSTUV-345678"
        ]
    }
}
 

Example response (400):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Two-factor authentication is already enabled",
    "data": null
}
 

Example response (401):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "User not authenticated",
    "data": null
}
 

Example response (422):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "The method field must be either email or sms",
    "data": null
}
 

Request      

POST api/admin/two-factor-auth/enable

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

method   string   

The 2FA method to use (email or sms). Example: email

Disable 2FA

requires authentication

Disables two-factor authentication for the authenticated admin user.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/two-factor-auth/disable" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/two-factor-auth/disable"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Two-factor authentication has been disabled",
    "data": null
}
 

Example response (400):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Two-factor authentication is not enabled",
    "data": null
}
 

Example response (401):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "User not authenticated",
    "data": null
}
 

Request      

POST api/admin/two-factor-auth/disable

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Change 2FA method

requires authentication

Changes the two-factor authentication method for the authenticated admin user.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/two-factor-auth/change-method" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"method\": \"sms\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/two-factor-auth/change-method"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "method": "sms"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Two-factor authentication method has been changed to sms",
    "data": null
}
 

Example response (400):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Two-factor authentication is not enabled",
    "data": null
}
 

Example response (401):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "User not authenticated",
    "data": null
}
 

Example response (422):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "The method field must be either email or sms",
    "data": null
}
 

Request      

POST api/admin/two-factor-auth/change-method

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

method   string   

The new 2FA method to use (email or sms). Example: sms

Generate verification code

requires authentication

Generates and sends a new verification code to the admin user via their chosen method (email or SMS).

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/two-factor-auth/generate-code" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/two-factor-auth/generate-code"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Verification code has been sent to your email",
    "data": {
        "method": "email"
    }
}
 

Example response (400):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Two-factor authentication is not enabled",
    "data": null
}
 

Example response (401):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "User not authenticated",
    "data": null
}
 

Request      

POST api/admin/two-factor-auth/generate-code

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Verify 2FA code

requires authentication

Verifies a two-factor authentication code for the authenticated admin user.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/two-factor-auth/verify-code" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"code\": \"123456\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/two-factor-auth/verify-code"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "code": "123456"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Two-factor authentication has been confirmed",
    "data": null
}
 

Example response (400):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Invalid verification code",
    "data": null
}
 

Example response (401):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "User not authenticated",
    "data": null
}
 

Example response (422):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "The code must be 6 characters",
    "data": null
}
 

Request      

POST api/admin/two-factor-auth/verify-code

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

code   string   

The 6-digit verification code. Example: 123456

Verify recovery code

requires authentication

Verifies a recovery code for the authenticated admin user. Recovery codes can be used when the user doesn't have access to their primary 2FA method.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/two-factor-auth/verify-recovery-code" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"recovery_code\": \"ABCDEF-123456\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/two-factor-auth/verify-recovery-code"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "recovery_code": "ABCDEF-123456"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Recovery code verified successfully",
    "data": {
        "remaining_codes": 7
    }
}
 

Example response (400):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Invalid recovery code",
    "data": null
}
 

Example response (401):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "User not authenticated",
    "data": null
}
 

Example response (422):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "The recovery code field is required",
    "data": null
}
 

Request      

POST api/admin/two-factor-auth/verify-recovery-code

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

recovery_code   string   

The recovery code to verify. Example: ABCDEF-123456

Regenerate recovery codes

requires authentication

Generates a new set of recovery codes for the authenticated admin user. This invalidates all previously generated recovery codes.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/two-factor-auth/regenerate-recovery-codes" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/two-factor-auth/regenerate-recovery-codes"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Recovery codes have been regenerated",
    "data": {
        "recovery_codes": [
            "ABCDEF-123456",
            "GHIJKL-789012",
            "MNOPQR-345678",
            "STUVWX-901234",
            "YZABCD-567890",
            "EFGHIJ-123456",
            "KLMNOP-789012",
            "QRSTUV-345678"
        ]
    }
}
 

Example response (400):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Two-factor authentication is not enabled",
    "data": null
}
 

Example response (401):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "User not authenticated",
    "data": null
}
 

Request      

POST api/admin/two-factor-auth/regenerate-recovery-codes

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Agent Management

List all agents

requires authentication

Retrieves a paginated list of all agents along with summary statistics, status overview, and monthly analytics data.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/agents?page=1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/agents"
);

const params = {
    "page": "1",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Agents data retrieved successfully",
    "data": {
        "summary": {
            "total_collections": 500000,
            "total_withdrawals": 200000,
            "earned_interest": 40000,
            "outstanding_balance": 300000,
            "total_agents": 50
        },
        "agents_status": {
            "total": 50,
            "active": 45,
            "inactive": 5,
            "active_percentage": 90,
            "inactive_percentage": 10
        },
        "analytics": {
            "labels": [
                "Jan",
                "Feb",
                "Mar",
                "Apr",
                "May",
                "Jun",
                "Jul",
                "Aug",
                "Sep",
                "Oct",
                "Nov",
                "Dec"
            ],
            "datasets": [
                {
                    "label": "Collections",
                    "data": [
                        10000,
                        15000,
                        20000,
                        25000,
                        30000,
                        35000,
                        40000,
                        45000,
                        50000,
                        55000,
                        60000,
                        65000
                    ],
                    "backgroundColor": "#F6C000"
                },
                {
                    "label": "Withdrawals",
                    "data": [
                        5000,
                        7500,
                        10000,
                        12500,
                        15000,
                        17500,
                        20000,
                        22500,
                        25000,
                        27500,
                        30000,
                        32500
                    ],
                    "backgroundColor": "#000000"
                }
            ]
        },
        "agents": {
            "data": [
                {
                    "id": 1,
                    "name": "John Doe",
                    "email": "[email protected]",
                    "phone": "+1234567890",
                    "status": {
                        "id": 1,
                        "name": "active"
                    },
                    "location": {
                        "country": "Nigeria",
                        "state": "Lagos",
                        "lga": "Ikeja"
                    },
                    "created_at": "2023-01-01T12:00:00.000000Z",
                    "updated_at": "2023-01-01T12:00:00.000000Z"
                }
            ],
            "links": {
                "first": "http://example.com/api/admin/agents?page=1",
                "last": "http://example.com/api/admin/agents?page=5",
                "prev": null,
                "next": "http://example.com/api/admin/agents?page=2"
            },
            "meta": {
                "current_page": 1,
                "from": 1,
                "last_page": 5,
                "path": "http://example.com/api/admin/agents",
                "per_page": 10,
                "to": 10,
                "total": 50
            }
        }
    }
}
 

Example response (500):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Internal server error",
    "data": null
}
 

Request      

GET api/admin/agents

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Query Parameters

page   integer  optional  

Page number for pagination. Example: 1

requires authentication

Searches for agents by name, email, phone or location.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/agents/search?search=John" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/agents/search"
);

const params = {
    "search": "John",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Agents found",
    "data": [
        {
            "id": 1,
            "name": "John Doe",
            "email": "[email protected]",
            "phone": "+1234567890",
            "status": {
                "id": 1,
                "name": "active"
            },
            "location": {
                "country": "Nigeria",
                "state": "Lagos",
                "lga": "Ikeja"
            }
        },
        {
            "id": 2,
            "name": "Jane Doe",
            "email": "[email protected]",
            "phone": "+2347012345678",
            "status": {
                "id": 2,
                "name": "inactive"
            },
            "location": {
                "country": "Nigeria",
                "state": "Abuja",
                "lga": "Kuje"
            }
        }
    ]
}
 

Get agent details

requires authentication

Retrieves detailed information about a specific agent including their personal details, financial summary, and transaction history.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/agents/agent/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/agents/agent/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Agent details retrieved successfully",
    "data": {
        "agent": {
            "id": 1,
            "name": "John Doe",
            "email": "[email protected]",
            "phone": "+1234567890",
            "status": {
                "id": 1,
                "name": "active"
            },
            "location": {
                "country": "Nigeria",
                "state": "Lagos",
                "lga": "Ikeja",
                "address": "123 Main Street"
            },
            "bank_details": {
                "bank_name": "Example Bank",
                "account_number": "1234567890",
                "account_name": "John Doe"
            },
            "created_at": "2023-01-01T12:00:00.000000Z",
            "updated_at": "2023-01-01T12:00:00.000000Z"
        },
        "financial_summary": {
            "balance": 50000,
            "total_collections": 100000,
            "total_withdrawals": 50000,
            "total_traders": 10
        },
        "recent_transactions": [
            {
                "id": 1,
                "type": "deposit",
                "amount": 10000,
                "status": {
                    "id": 1,
                    "name": "completed"
                },
                "trader": {
                    "id": 1,
                    "name": "Jane Smith"
                },
                "created_at": "2023-01-01T12:00:00.000000Z"
            }
        ]
    }
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Agent not found",
    "data": null
}
 

Request      

GET api/admin/agents/agent/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the agent. Example: 1

Toggle agent status

requires authentication

Blocks or unblocks an agent account. When blocked, the agent cannot access the system or perform any transactions.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/agents/1/toggle-block" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"reason\": \"Suspicious activity detected\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/agents/1/toggle-block"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "reason": "Suspicious activity detected"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200, Blocked):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Agent blocked successfully",
    "data": {
        "id": 1,
        "name": "John Doe",
        "status": {
            "id": 2,
            "name": "inactive"
        },
        "block_reason": "Suspicious activity detected",
        "updated_at": "2023-01-01T12:00:00.000000Z"
    }
}
 

Example response (200, Unblocked):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Agent unblocked successfully",
    "data": {
        "id": 1,
        "name": "John Doe",
        "status": {
            "id": 1,
            "name": "active"
        },
        "block_reason": null,
        "updated_at": "2023-01-01T12:00:00.000000Z"
    }
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Agent not found",
    "data": null
}
 

Request      

POST api/admin/agents/{id}/toggle-block

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the agent. Example: 1

Body Parameters

reason   string   

Reason for blocking/unblocking the agent. Example: Suspicious activity detected

Delete agent

requires authentication

Permanently deletes an agent account and all associated data. This action cannot be undone.

Example request:
curl --request DELETE \
    "https://api.sabisave.com/api/admin/agents/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/agents/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "DELETE",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Agent deleted successfully",
    "data": null
}
 

Example response (400):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Cannot delete agent with active balance",
    "data": null
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Agent not found",
    "data": null
}
 

Request      

DELETE api/admin/agents/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the agent. Example: 1

Agent Transactions

List agent transactions

requires authentication

Retrieves a paginated list of agent transactions with optional filtering by agent ID, date range, transaction type, and status.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/agents/transactions?agent_id=1&start_date=2023-01-01&end_date=2023-12-31&type=deposit&status_id=1&page=1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/agents/transactions"
);

const params = {
    "agent_id": "1",
    "start_date": "2023-01-01",
    "end_date": "2023-12-31",
    "type": "deposit",
    "status_id": "1",
    "page": "1",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Transactions retrieved successfully",
    "data": {
        "transactions": {
            "current_page": 1,
            "data": [
                {
                    "id": 1,
                    "agent": {
                        "id": 1,
                        "name": "John Doe"
                    },
                    "trader": {
                        "id": 1,
                        "name": "Jane Smith"
                    },
                    "type": "deposit",
                    "amount": 10000,
                    "status": {
                        "id": 1,
                        "name": "completed"
                    },
                    "created_at": "2023-01-01T12:00:00.000000Z"
                }
            ],
            "first_page_url": "http://example.com/api/admin/agents/transactions?page=1",
            "from": 1,
            "last_page": 5,
            "last_page_url": "http://example.com/api/admin/agents/transactions?page=5",
            "links": [],
            "next_page_url": "http://example.com/api/admin/agents/transactions?page=2",
            "path": "http://example.com/api/admin/agents/transactions",
            "per_page": 10,
            "prev_page_url": null,
            "to": 10,
            "total": 50
        },
        "summary": {
            "total_amount": 500000,
            "total_count": 50
        }
    }
}
 

Example response (500):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Internal server error",
    "data": null
}
 

Request      

GET api/admin/agents/transactions

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Query Parameters

agent_id   integer  optional  

ID of the agent to filter transactions. Example: 1

start_date   string  optional  

date Start date for filtering transactions (YYYY-MM-DD). Example: 2023-01-01

end_date   string  optional  

date End date for filtering transactions (YYYY-MM-DD). Example: 2023-12-31

type   string  optional  

Transaction type (deposit/withdrawal). Example: deposit

status_id   integer  optional  

Status ID for filtering transactions. Example: 1

page   integer  optional  

Page number for pagination. Example: 1

Agents

APIs for Agents

Agent Login.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/login" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"agent_number\": \"8013221673\",
    \"password\": \"12345678\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/login"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "agent_number": "8013221673",
    "password": "12345678"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
  "status": 1,
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
  "refresh_token": "def50200ea86c5d6161c...",
  "expire_at": "29-06-24 14:57:10",
  "token_type": "Bearer",
  "message": "Successfully logged in",
  "agent": {
      "id": 1,
      "name": "John Doe",
      "agent_number": "8013221673",
      "email": "[email protected]",
      ...
  }
}
 

Example response (422):


{
    "message": "Invalid data sent",
    "details": {
        "agent_id": [
            "The agent id field is required."
        ],
        "password": [
            "The password must be at least 6 characters."
        ]
    }
}
 

Request      

POST api/agents/login

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

agent_number   string   

The agent number of the agent. Example: 8013221673

password   string   

The password of the agent. Minimum length of 6 characters. Example: 12345678

Create Agent Step 1.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/register-step-1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"username\": \"user_name\",
    \"email\": \"[email protected]\",
    \"phone\": \"08013221673\",
    \"trader_union\": \"user trader_union\",
    \"password\": \"12345678\",
    \"first_name\": \"John\",
    \"last_name\": \"mark\",
    \"gender\": \"male\",
    \"dob\": \"2024-03-09\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/register-step-1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "username": "user_name",
    "email": "[email protected]",
    "phone": "08013221673",
    "trader_union": "user trader_union",
    "password": "12345678",
    "first_name": "John",
    "last_name": "mark",
    "gender": "male",
    "dob": "2024-03-09"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (201):


{
    "data": {
        "id": 4,
        "trader_union": "user trader_union",
        "email": "[email protected]",
        "username": "user_name",
        "password": "12345678",
        "first_name": "John",
        "last_name": "mark",
        "phone": "08013221673",
        "gender": "male",
        "dob": "2024-03-09"
    }
}
 

Example response (422):


{
    "message": "Invalid data sent",
    "details": {
        "email": [
            "The email field is required."
        ],
        "password": [
            "The password must be at least 8 characters."
        ]
    }
}
 

Request      

POST api/agents/register-step-1

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

username   string   

The username of the user. Example: user_name

email   string   

The email of the user. Example: [email protected]

phone   string   

The phone number of the user. Example: 08013221673

trader_union   string   

The trader union of the user. Example: user trader_union

password   string   

The password of the user. Example: 12345678

first_name   string   

The first name of the user. Example: John

last_name   string   

The last name of the user. Example: mark

gender   string   

The gender of the user. Example: male

dob   date   

The date of birth of the user. Example: 2024-03-09

Complete agent registration step 2.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/register-step-2" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"agent_id\": 1,
    \"country_id\": \"1\",
    \"state_id\": \"1\",
    \"lga_id\": \"1\",
    \"address\": \"\\\"123 Street, City, State\\\"\",
    \"post_code\": \"\\\"100001\\\"\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/register-step-2"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "agent_id": 1,
    "country_id": "1",
    "state_id": "1",
    "lga_id": "1",
    "address": "\"123 Street, City, State\"",
    "post_code": "\"100001\""
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Agent step 2 registration completed",
    "data": {
        "id": 1,
        "trader_union": "user trader_union",
        "email": "[email protected]",
        "username": "user_name",
        "password": "12345678",
        "first_name": "John",
        "last_name": "mark",
        "phone": "08013221673",
        "gender": "male",
        "dob": "2024-03-09",
        "country_id": "Nigeria",
        "state_id": "Abia State",
        "lga_id": "Ikwuano",
        "address": "5 cape ville",
        "post_code": "10090"
    }
}
 

Example response (403):


{
    "message": "User not verified",
    "details": []
}
 

Example response (404):


{
    "message": "Agent not found",
    "details": []
}
 

Request      

POST api/agents/register-step-2

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

agent_id   integer   

The ID of the agent. Example: 1

country_id   numeric   

The ID of the country. Example: 1

state_id   numeric   

The ID of the state. Example: 1

lga_id   numeric   

The ID of the local government area. Example: 1

address   string   

The address of the agent. Example: "123 Street, City, State"

post_code   string   

The postal code of the agent's address. Example: "100001"

Create a new transaction PIN for an agent.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/transaction-pin" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"pin\": \"1234\",
    \"pin_confirmation\": \"1234\",
    \"agent_id\": 1
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/transaction-pin"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "pin": "1234",
    "pin_confirmation": "1234",
    "agent_id": 1
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (201):


{
    "message": "Transaction PIN created successfully",
    "data": {
        "agent_id": "8013221673"
    },
    "meta-links": []
}
 

Example response (404):


{
    "message": "Agent not found",
    "details": {
        "error": "Agent not found"
    }
}
 

Example response (500):


{
    "message": "Failed to create transaction PIN",
    "details": {
        "error": "Internal Server Error"
    }
}
 

Request      

POST api/agents/transaction-pin

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

pin   string   

The PIN of the transaction. Example: 1234

pin_confirmation   string   

The confirmation of the PIN. Example: 1234

agent_id   integer   

The ID of the agent. Example: 1

Profile image upload.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/uploadid" \
    --header "Content-Type: multipart/form-data" \
    --header "Accept: application/json" \
    --form "agent_id=1"\
    --form "id_type=passport"\
    --form "id_file=@/tmp/phppEc41s" 
const url = new URL(
    "https://api.sabisave.com/api/agents/uploadid"
);

const headers = {
    "Content-Type": "multipart/form-data",
    "Accept": "application/json",
};

const body = new FormData();
body.append('agent_id', '1');
body.append('id_type', 'passport');
body.append('id_file', document.querySelector('input[name="id_file"]').files[0]);

fetch(url, {
    method: "POST",
    headers,
    body,
}).then(response => response.json());

Example response (200):


{
  "message": "File uploaded successfully",

}
 

Example response (500):


{
    "message": "Failed to create ID",
    "error": "Error message"
}
 

Request      

POST api/agents/uploadid

Headers

Content-Type      

Example: multipart/form-data

Accept      

Example: application/json

Body Parameters

agent_id   string   

The ID of the agent. Example: 1

id_type   string   

The type of ID. Example: passport

id_file   file   

The file of the ID. Example: /tmp/phppEc41s

Updates the transaction PIN for the specified agent.

requires authentication

This endpoint updates the transaction PIN for an agent after verifying a one-time password (OTP) sent to the agent's phone.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/update-transaction-pin" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"pin\": \"fugiat\",
    \"pin_confirmation\": \"aliquid\",
    \"otp\": \"tempora\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/update-transaction-pin"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "pin": "fugiat",
    "pin_confirmation": "aliquid",
    "otp": "tempora"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Transaction PIN updated successfully"
}
 

Example response (400):


{
    "error": "Invalid OTP",
    "message": "Invalid OTP provided"
}
 

Example response (500):


{"error": "Failed to update transaction PIN", "message": "Failed to update transaction PIN"}

Example Request:
{
  "pin": "1234",
  "pin_confirmation": "1234",
  "otp": "5678"
}

Example Response (Success):
{
  "message": "Transaction PIN updated successfully"
}

Example Response (Invalid OTP):
{
  "error": "Invalid OTP",
  "message": "Invalid OTP provided"
}

Example Response (Failed to update transaction PIN):
{
  "error": "Failed to update transaction PIN",
  "message": "Failed to update transaction PIN"
}
 

Request      

POST api/agents/update-transaction-pin

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

pin   string   

The new transaction PIN for the agent. Must be numeric and exactly 4 digits. Example: fugiat

pin_confirmation   string   

The confirmation of the new transaction PIN. Example: aliquid

otp   string   

The one-time password sent to the agent's phone. Must be numeric and exactly 4 digits. Example: tempora

Updates the profile image for the specified agent.

requires authentication

This endpoint updates the profile image for an agent after verifying a one-time password (OTP) sent to the agent's phone.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/update-profile-image" \
    --header "Content-Type: multipart/form-data" \
    --header "Accept: application/json" \
    --form "profile_image=@/tmp/php7Zz5vy" 
const url = new URL(
    "https://api.sabisave.com/api/agents/update-profile-image"
);

const headers = {
    "Content-Type": "multipart/form-data",
    "Accept": "application/json",
};

const body = new FormData();
body.append('profile_image', document.querySelector('input[name="profile_image"]').files[0]);

fetch(url, {
    method: "POST",
    headers,
    body,
}).then(response => response.json());

Example response (200):


{
    "message": "image updated successfully"
}
 

Example response (400):


{
    "error": "Invalid OTP",
    "message": "Invalid OTP provided"
}
 

Example response (500):


{
    "error": "Failed to update profile image",
    "message": "Failed to update profile image"
}
 

Request      

POST api/agents/update-profile-image

Headers

Content-Type      

Example: multipart/form-data

Accept      

Example: application/json

Body Parameters

profile_image   file  optional  

nullable The profile image of the agent. Must be in JPEG, PNG, or JPG format and cannot exceed 1MB in size. Example: /tmp/php7Zz5vy

Deactivate/delete an agent account.

requires authentication

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/deactivate/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"delete_phrase\": \"\\\"delete_johndoe\\\".\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/deactivate/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "delete_phrase": "\"delete_johndoe\"."
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Agent deleted successfully"
}
 

Example response (400):


{
    "error": "Invalid delete phrase",
    "message": "Invalid delete phrase provided"
}
 

Example response (500):


{
    "error": "Failed to delete agent",
    "message": "Failed to delete agent"
}
 

Request      

POST api/agents/deactivate/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the deactivate. Example: 1

Body Parameters

delete_phrase   string   

The delete phrase to verify the deletion. Example: "delete_johndoe".

Delete agent account

requires authentication

Permanently deletes an agent account and all associated data. This action cannot be undone.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/delete-account/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/agents/delete-account/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Agent deleted successfully",
    "data": null
}
 

Example response (400):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Cannot delete agent with active balance",
    "data": null
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Agent not found",
    "data": null
}
 

Request      

POST api/agents/delete-account/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the agent. Example: 1

Reactivate an agent account.

requires authentication

This endpoint reactivates an agent account that has been previously deactivated.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/reactivate" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"agent_id\": 1
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/reactivate"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "agent_id": 1
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Agent restored successfully"
}
 

Example response (404):


{
    "error": "Agent not found",
    "message": "Agent not found"
}
 

Request      

POST api/agents/reactivate

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

agent_id   integer   

The ID of the agent to reactivate. Example: 1

Update the password for the specified agent.

requires authentication

This endpoint updates the password for an agent after verifying the current password and a one-time password (OTP) sent to the agent's phone.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/change-password" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"password\": \"`zcLcq\",
    \"password_confirmation\": \"id\",
    \"current_password\": \"alias\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/change-password"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "password": "`zcLcq",
    "password_confirmation": "id",
    "current_password": "alias"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Password updated successfully"
}
 

Example response (400):


{
    "error": "In correct password",
    "message": "Current password does not match"
}
 

Example response (500):


{
    "error": "Failed to update password",
    "message": "Failed to update password"
}
 

Request      

POST api/agents/change-password

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

password   string   

The new password for the agent. Must be at least 8 characters. Example: `zcLcq

password_confirmation   string   

The confirmation of the new password. Example: id

current_password   string   

The current password of the agent. Must be at least 8 characters. Example: alias

Update the profile for the specified agent.

requires authentication

This endpoint updates the profile information for an agent after verifying a one-time password (OTP) sent to the agent's phone.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/update-profile" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"first_name\": \"et\",
    \"last_name\": \"sunt\",
    \"email\": \"[email protected]\",
    \"phone\": \"eius\",
    \"gender\": \"distinctio\",
    \"dob\": \"animi\",
    \"trader_union\": \"recusandae\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/update-profile"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "first_name": "et",
    "last_name": "sunt",
    "email": "[email protected]",
    "phone": "eius",
    "gender": "distinctio",
    "dob": "animi",
    "trader_union": "recusandae"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Profile updated successfully"
}
 

Example response (500):


{
    "error": "Failed to update profile",
    "message": "Failed to update profile"
}
 

Request      

POST api/agents/update-profile

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

first_name   string  optional  

nullable The first name of the agent. Maximum length is 255 characters. Example: et

last_name   string  optional  

nullable The last name of the agent. Maximum length is 255 characters. Example: sunt

email   string  optional  

nullable The email address of the agent. Must be a valid email address and maximum length is 255 characters. Example: [email protected]

phone   string  optional  

nullable The phone number of the agent. Maximum length is 255 characters. Example: eius

gender   string  optional  

nullable The gender of the agent. Example: distinctio

dob   date  optional  

nullable The date of birth of the agent. Example: animi

trader_union   string  optional  

nullable The trader union of the agent. Maximum length is 255 characters. Example: recusandae

Update the bank details for the specified agent.

requires authentication

This endpoint updates the bank details for an agent.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/update-bank-details" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"bank_name\": \"\\\"First Bank of Nigeria\\\"\",
    \"account_type\": \"\\\"Savings\\\"\",
    \"account_number\": \"0123456789\",
    \"account_name\": \"\\\"John Doe\\\"\",
    \"bank_code\": \"\\\"011\\\"\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/update-bank-details"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "bank_name": "\"First Bank of Nigeria\"",
    "account_type": "\"Savings\"",
    "account_number": "0123456789",
    "account_name": "\"John Doe\"",
    "bank_code": "\"011\""
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Bank details updated successfully"
}
 

Example response (400):


{
    "error": "Failed to update bank details",
    "message": "Failed to update bank details"
}
 

Example response (500):


{
    "error": "Failed to update bank details",
    "message": "Failed to update bank details"
}
 

Request      

POST api/agents/update-bank-details

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

bank_name   string   

The name of the bank. Maximum length is 255 characters. Example: "First Bank of Nigeria"

account_type   string  optional  

nullable The type of the account. Maximum length is 255 characters. Example: "Savings"

account_number   numeric   

The account number of the agent. Must be a numeric value and must be between 10 and 12 digits. Example: 0123456789

account_name   string   

The account name of the agent. Maximum length is 255 characters. Example: "John Doe"

bank_code   string   

The bank code of the agent. Maximum length is 255 characters. Example: "011"

GET api/agents/transactions/getall

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/agents/transactions/getall" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/agents/transactions/getall"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (403):

Show headers
cache-control: no-cache, private
content-type: application/json
vary: Origin
 

{
    "status": false,
    "message": "Unauthorize"
}
 

Request      

GET api/agents/transactions/getall

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Get the balance of the authenticated agent

requires authentication

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/agents/balance" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/agents/balance"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Balance retrieved successfully",
    "data": {
        "balance": 1000
    }
}
 

Example response (404):


{
    "message": "Agent not found"
}
 

Request      

GET api/agents/balance

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Retrieve a single transaction by id

requires authentication

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/agents/transactions/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/agents/transactions/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
  "message": "Transaction retrieved successfully",
  "data": {
      "id": 1,
      "amount": 10000,
      "type": "debit",
      "trader": {
          "id": 1,
          "phone": "08132221963",
          "full_name": "Super Admin",
          "other_name": null,
          "email": "[email protected]",
          "dob": "2016-07-29",
          "gender": "male",
          "has_cooperative": true,
          "cooperative": "Cronin-Kshlerin",
          "username": "super-admin",
          "balance": 980000,
          "account_number": "8132221963",
          "bank_details": {
              "id": 19,
              "bank_name": "UBA",
              "account_type": "savings",
              "account_number": "0737775790",
              "bank_code": "857"
          },
          "created_at": "2025-06-04 08:37:18",
          "updated_at": "2025-06-04 08:37:18"
      },
      "recipient": "agent",
      "status": "completed",
      "agent": {
          "id": 1,
          "trader_union": "nihil",
          "email": "[email protected]",
          "username": "super-admin",
          "first_name": "Super",
          "last_name": "Admin",
          "phone": "08132221963",
          "gender": "female",
          "dob": "1999-08-15T00:00:00.000000Z",
          "country": "Nigeria",
          "state": "Lagos State",
          "lga": "Ikeja",
          "address": "9957 Rafael Viaduct\nHirtheview, NJ 18671",
          "post_code": "04387-0972",
          "profile": "https://via.placeholder.com/640x480.png/00aaaa?text=exercitationem",
          "agent_number": "08132221963",
          "balance": 9980000,
          "bank_details": {
              "id": 1,
              "bank_name": "GTB",
              "account_type": "savings",
              "account_number": "23298140144727",
              "bank_code": "058"
          }
      },
      "created_at": "2025-06-06 02:42:31",
      "updated_at": "2025-06-06 02:42:31",
      "reference": null
  }
 

Example response (404):


{
    "message": "Transaction not found",
    "details": {
        "error": "Transaction not found"
    }
}
 

Request      

GET api/agents/transactions/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the transaction. Example: 1

Step one of trader onboarding process

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/trader-onboarding/step-1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"phone\": \"09031922234\",
    \"full_name\": \"John Smith\",
    \"other_name\": \"Abraham\",
    \"gender\": \"male\",
    \"dob\": \"2000-01-15\",
    \"has_cooperative\": true,
    \"cooperative\": \"Ikokun Cooperative\",
    \"password\": \"Pass@123\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/trader-onboarding/step-1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "phone": "09031922234",
    "full_name": "John Smith",
    "other_name": "Abraham",
    "gender": "male",
    "dob": "2000-01-15",
    "has_cooperative": true,
    "cooperative": "Ikokun Cooperative",
    "password": "Pass@123"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (201):


{
    "data": {
        "id": 4,
        "full_name": "John Smith",
        "other_name": "Abraham",
        "phone": "+2348013221673",
        "gender": "male",
        "dob": "2000-01-15",
        "has_cooperative": true,
        "cooperative": "Ikokun Cooperative"
    }
}
 

Example response (422):


{
    "message": "Invalid data sent",
    "details": {
        "email": [
            "The email field is required."
        ],
        "password": [
            "The password must be at least 8 characters."
        ]
    }
}
 

Request      

POST api/agents/trader-onboarding/step-1

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

phone   string   

The phone number of the trader. Example: 09031922234

full_name   string   

The full name of the trader. Example: John Smith

other_name   string  optional  

optional The other name of the trader. Example: Abraham

gender   string   

The gender of the trader (male or female). Example: male

dob   date   

The date of birth of the trader. Example: 2000-01-15

has_cooperative   boolean   

Whether the user belongs to a cooperative. Example: true

cooperative   string  optional  

optional The cooperative name (required if has_cooperative is true). Example: Ikokun Cooperative

password   string   

The password of the trader. Example: Pass@123

Complete Trader registration step 2

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/trader-onboarding/step-2" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"trader_id\": 1,
    \"country_id\": 1,
    \"state_id\": 1,
    \"lga_id\": 1,
    \"address\": \"\\\"123 Street, City, State\\\"\",
    \"post_code\": \"\\\"100001\\\"\",
    \"business_type\": \"retail\",
    \"is_registered_with_CAC\": true,
    \"business_name\": \"SABISAVE\",
    \"reg_number\": \"1234567\",
    \"savings_frequency\": \"daily\",
    \"savings_amount\": \"1000\",
    \"account_type\": \"current\",
    \"bank_name\": \"GTB\",
    \"bank_code\": \"058\",
    \"account_number\": \"100001300\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/trader-onboarding/step-2"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "trader_id": 1,
    "country_id": 1,
    "state_id": 1,
    "lga_id": 1,
    "address": "\"123 Street, City, State\"",
    "post_code": "\"100001\"",
    "business_type": "retail",
    "is_registered_with_CAC": true,
    "business_name": "SABISAVE",
    "reg_number": "1234567",
    "savings_frequency": "daily",
    "savings_amount": "1000",
    "account_type": "current",
    "bank_name": "GTB",
    "bank_code": "058",
    "account_number": "100001300"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (112):


{
    "message": "unable to register user",
    "details": []
}
 

Example response (200):


{
  "message": "Trader registration completed",
  "data": {
      "id": 1,
      "cooperative": "user cooperative",
      "email": "[email protected]",
      "password": "12345678",
      "first_name": "John",
      "mid_name":Doe
      "last_name": "mark",
      "phone": "08013221673",
      "gender": "male",
      "dob": "2024-03-09",
      "country_id": "Nigeria",
      "state_id": "Abia State",
      "lga_id": "Ikwuano",
      "address": "5 cape ville",
      "post_code": "10090",
      "frequency": "daily",
      "amount": "1000"
  }
}
 

Example response (403):


{
    "message": "User not verified",
    "details": []
}
 

Example response (404):


{
    "message": "Trader not found",
    "details": []
}
 

Request      

POST api/agents/trader-onboarding/step-2

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

trader_id   integer   

The ID of the trader. Example: 1

country_id   integer   

The ID of the country. Example: 1

state_id   integer   

The ID of the state. Example: 1

lga_id   integer   

The ID of the local government area. Example: 1

address   string   

The address of the trader. Example: "123 Street, City, State"

post_code   string  optional  

nullable The postal code of the trader's address. Example: "100001"

business_type   string   

The type of business. Example: retail

is_registered_with_CAC   boolean   

Is the trader registered with CAC. Example: true

business_name   string   

The name of the trader's business. Example: SABISAVE

reg_number   string   

The business registration number. Example: 1234567

savings_frequency   string   

The savings frequency. Example: daily

savings_amount   numeric   

The savings amount. Example: 1000

account_type   string   

If the trader has a bank account. Example: current

bank_name   string  optional  

sometimes The name of the bank. Example: GTB

bank_code   string   

If the trader has a bank account. Example: 058

account_number   string   

If the trader has a bank account. Example: 100001300

Create a new transaction PIN for a trader.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/trader-onboarding/create-pin" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"pin\": \"1234\",
    \"pin_confirmation\": \"1234\",
    \"trader_id\": 1
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/trader-onboarding/create-pin"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "pin": "1234",
    "pin_confirmation": "1234",
    "trader_id": 1
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (201):


{
    "message": "Transaction PIN created successfully",
    "data": {
        "trader_id": 1
    },
    "meta-links": []
}
 

Example response (404):


{
    "message": "Trader not found",
    "details": {
        "error": "Trader not found"
    }
}
 

Example response (500):


{
    "message": "Failed to create transaction PIN",
    "details": {
        "error": "Internal Server Error"
    }
}
 

Request      

POST api/agents/trader-onboarding/create-pin

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

pin   string   

The PIN of the transaction. Example: 1234

pin_confirmation   string   

The confirmation of the PIN. Example: 1234

trader_id   integer   

The ID of the trader. Example: 1

Uploads a profile picture for the specified trader.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/trader-onboarding/upload-profile-pic" \
    --header "Content-Type: multipart/form-data" \
    --header "Accept: application/json" \
    --form "trader_id=8"\
    --form "profile_image=@/tmp/phpc17JGz" 
const url = new URL(
    "https://api.sabisave.com/api/agents/trader-onboarding/upload-profile-pic"
);

const headers = {
    "Content-Type": "multipart/form-data",
    "Accept": "application/json",
};

const body = new FormData();
body.append('trader_id', '8');
body.append('profile_image', document.querySelector('input[name="profile_image"]').files[0]);

fetch(url, {
    method: "POST",
    headers,
    body,
}).then(response => response.json());

Example response (200):


{
    "message": "Profile image updated successfully",
    "data": {
        "profile_image": "/storage/profile/image.jpg",
        "trader_number": "TRD001"
    }
}
 

Example response (400):


{
    "message": "Validation failed",
    "error": {
        "code": 400,
        "message": "Validation failed",
        "data": {
            "profile_image": [
                "The profile image field is required."
            ]
        }
    }
}
 

Example response (500):


{
    "message": "Internal server error",
    "error": {
        "code": 500,
        "message": "Server error details"
    }
}
 

Request      

POST api/agents/trader-onboarding/upload-profile-pic

Headers

Content-Type      

Example: multipart/form-data

Accept      

Example: application/json

Body Parameters

profile_image   file   

The profile image of the trader. Must be an image (jpeg, png, jpg, gif) and less than 2MB in size. Example: /tmp/phpc17JGz

trader_id   integer   

The ID of the trader. Example: 8

Upload ID for a trader.

requires authentication

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/trader-onboarding/upload-id" \
    --header "Content-Type: multipart/form-data" \
    --header "Accept: application/json" \
    --form "trader_id=1"\
    --form "id_type=passport"\
    --form "id_file=@/tmp/phpgShOz4" 
const url = new URL(
    "https://api.sabisave.com/api/agents/trader-onboarding/upload-id"
);

const headers = {
    "Content-Type": "multipart/form-data",
    "Accept": "application/json",
};

const body = new FormData();
body.append('trader_id', '1');
body.append('id_type', 'passport');
body.append('id_file', document.querySelector('input[name="id_file"]').files[0]);

fetch(url, {
    method: "POST",
    headers,
    body,
}).then(response => response.json());

Example response (200):


{
    "message": "File uploaded successfully"
}
 

Example response (500):


{
    "message": "Failed to create ID",
    "error": "Error message"
}
 

Request      

POST api/agents/trader-onboarding/upload-id

Headers

Content-Type      

Example: multipart/form-data

Accept      

Example: application/json

Body Parameters

trader_id   string   

The ID of the trader. Example: 1

id_type   string   

The type of ID. Example: passport

id_file   file   

The file of the ID. Must be of type jpeg, png, jpg, gif, svg, pdf and not exceed 1MB. Example: /tmp/phpgShOz4

Get a single trader

requires authentication

This endpoint returns a single trader belonging to the authenticated agent

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/agents/trader/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/agents/trader/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Trader found successfully",
    "data": {
        "id": 2,
        "full_name": "Ibraheem Razaq",
        "email": "[email protected]",
        "phone": "+2348016067",
        "gender": "Male",
        "dob": "12/08/1990",
        "address": "No 18 Allen Str Ikeja",
        "customer_id": "802430840",
        "trader_level": "Silver Level",
        "account_status": "verified",
        "saving_plan": "Daily Saving Plan",
        "profile_image": "/storage/profile/image.jpg"
    }
}
 

Example response (404):


{
    "message": "Trader not found",
    "errors": []
}
 

Request      

GET api/agents/trader/{trader_id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

trader_id   integer   

The ID of the trader. Example: 1

trader   string   

The ID of the trader. Example: 2

Get recent collections

requires authentication

This endpoint returns a list of recent collections by the authenticated agent

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/agents/recent-collections?page=1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/agents/recent-collections"
);

const params = {
    "page": "1",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
  "message": "Collections retrieved successfully",
  "data": {
    "data": [
      {
        "amount": 4390,
        "type": "credit",
        "trader": {
          "id": 5,
          "phone": "325-367-7061",
          "full_name": "Marley Yost",
          "other_name": null,
          "email": "[email protected]",
          "username": "marley.yost164",
          "balance": 1000000,
          "account_number": "4967805157",
          "bank_details": {
              "id": 23,
              "bank_name": "UBA",
              "account_type": "savings",
              "account_number": "2062595419",
              "bank_code": "930"
          }
        },
        "agent_id": 1,
        "status": "remitted",
        "recipient": "agent",
        "reason": "Cash Deposit from Trader",
        "balance": null,
        "reference": null
      }
    "links": {
      "first": "http://localhost/api/admin/collections?page=1",
      "last": "http://localhost/api/admin/collections?page=5",
      "prev": null,
      "next": "http://localhost/api/admin/collections?page=2"
    },
    "meta": {
      "current_page": 1,
      "from": 1,
      "last_page": 5,
      "path": "http://localhost/api/admin/collections",
      "per_page": 10,
      "to": 10,
      "total": 50
    }
  }
}
 

Example response (404):


{
    "message": "No collection found",
    "errors": []
}
 

Request      

GET api/agents/recent-collections

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Query Parameters

page   string   

The page number to return. Example: 1

requires authentication

Retrieves a paginated list of traders filtered by account number or phone number and ensures the trader is associated with the authenticated agent.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/agents/trader-search?account_number=123456&phone=%2B1234567890" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/agents/trader-search"
);

const params = {
    "account_number": "123456",
    "phone": "+1234567890",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
  "data": [
     {
      "id": 1,
      "phone": "08132221963",
      "full_name": "Super Admin",
      "other_name": null,
      "email": "[email protected]",
      "username": "super-admin",
      "balance": 980000,
      "account_number": "8132221963",
      "bank_details": {
          "id": 19,
          "bank_name": "UBA",
          "account_type": "savings",
          "account_number": "0737775790",
          "bank_code": "857"
      }
  },
  ],
  "links": {
    "first": "http://example.com/api/traders?page=1",
    "last": "http://example.com/api/traders?page=5",
    "prev": null,
    "next": "http://example.com/api/traders?page=2"
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 5,
    "path": "http://example.com/api/traders",
    "per_page": 15,
    "to": 15,
    "total": 75
  }
}
 

Example response (404):


{
    "message": "No traders found",
    "errors": []
}
 

Get Top 10 Traders by Balance

requires authentication

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/agents/top-traders" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/agents/top-traders"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "data": [
        {
            "id": 1,
            "full_name": "John Doe",
            "email": "[email protected]",
            "phone": "+2348016067",
            "gender": "Male",
            "dob": "12/08/1990",
            "address": "No 18 Allen Str Ikeja",
            "customer_id": "802430840",
            "trader_level": "Silver Level",
            "account_status": "verified",
            "saving_plan": "Daily Saving Plan",
            "profile_image": "/storage/profile/image.jpg",
            "total_amount": 1000000
        }
    ],
    "links": {
        "first": "http://localhost/api/agent/top-traders?page=1",
        "last": "http://localhost/api/agent/top-traders?page=1",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "path": "http://localhost/api/agent/top-traders",
        "per_page": 10,
        "to": 10,
        "total": 10
    }
}
 

Example response (404):


{
    "message": "No traders found",
    "errors": []
}
 

Request      

GET api/agents/top-traders

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Get Agent Trader Statistics

requires authentication

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/agents/stats" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/agents/stats"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "success",
    "data": {
        "number_agent_traders": 10,
        "number_active_agent_traders": 5,
        "agent_balance": {
            "amount": 100000,
            "currency": "NGN"
        },
        "trader_plans": 5
    }
}
 

Request      

GET api/agents/stats

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Get the profile for the specified agent.

requires authentication

This endpoint retrieves the profile information for an agent.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/agents/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/agents/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "data": {
        "id": 1,
        "first_name": "John",
        "last_name": "Doe",
        "email": "[email protected]",
        "phone": "1234567890",
        "gender": "male",
        "dob": "1990-01-01"
    }
}
 

Example response (404):


{
    "error": "Agent not found",
    "message": "Agent not found"
}
 

Example response (500):


{
    "error": "Failed to get profile",
    "message": "Failed to get profile"
}
 

Request      

GET api/agents/{agent_id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

agent_id   integer   

The ID of the agent. Example: 1

Get all agents.

requires authentication

This endpoint retrieves all the agents in the system.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/agents?number=4" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/agents"
);

const params = {
    "number": "4",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{"data": [{"id": 1, "first_name": "John", "last_name": "Doe", "email": "[email protected]", "phone": "1234567890", "gender": "male", "dob": "1990-01-01"}, {"id": 2, "first_name": "Jane", "last_name": "Doe", "email": "[email protected]", "phone": "1234567890", "gender": "female", "dob": "1990-01-01"}, ...]}
 

Example response (500):


{
    "error": "Failed to get agents",
    "message": "Failed to get agents"
}
 

Request      

GET api/agents

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Query Parameters

number   integer  optional  

The number of agents to retrieve. Defaults to 10. Example: 4

Process a deposit for a trader.

requires authentication

Example request:
curl --request POST \
    "https://api.sabisave.com/api/deposits" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"trader_account_number\": 1,
    \"amount\": \"\\\"23000\\\"\",
    \"agent_id\": \"\\\"1\\\"\",
    \"pin\": \"\\\"1234\\\"\"
}"
const url = new URL(
    "https://api.sabisave.com/api/deposits"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "trader_account_number": 1,
    "amount": "\"23000\"",
    "agent_id": "\"1\"",
    "pin": "\"1234\""
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
  "message": "Deposit successful",

}
 

Example response (500):


{
    "message": "Deposit failed",
    "errors": []
}
 

Request      

POST api/deposits

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

trader_account_number   integer   

The account number of the trader. Example: 1

amount   string   

The amount to be deposited. Example: "23000"

agent_id   string   

The ID of the agent processing the deposit. Example: "1"

pin   string   

The PIN of the agent processing the deposit. Example: "1234"

Withdraw funds from trader to agent.

requires authentication

Requires Bearer Token Authentication.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/withdrawals" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"amount\": \"10000\",
    \"type\": \"\\\"cash\\\"\",
    \"account_number\": \"\\\"8012345678\\\"\",
    \"reason\": \"\\\"Savings withdrawal\\\"\",
    \"pin\": \"\\\"1234\\\"\"
}"
const url = new URL(
    "https://api.sabisave.com/api/withdrawals"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "amount": "10000",
    "type": "\"cash\"",
    "account_number": "\"8012345678\"",
    "reason": "\"Savings withdrawal\"",
    "pin": "\"1234\""
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Withdrawal request is being processed.",
    "data": [],
    "meta-links": []
}
 

Example response (400):


{
    "message": "Insufficient balance in Trader account"
}
 

Example response (400):


{
    "message": "Insufficient balance in Agent account"
}
 

Example response (404):


{
    "message": "Trader or Agent not found"
}
 

Example response (422):


{
    "message": "Validation Error",
    "errors": {
        "amount": [
            "The amount field is required."
        ],
        "type": [
            "The type field is required."
        ]
    }
}
 

Example response (500):


{
    "message": "Internal Server Error"
}
 

Request      

POST api/withdrawals

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

amount   numeric   

Amount to withdraw. Example: 10000

type   string   

Type of withdrawal: "cash" or "bank". Example: "cash"

account_number   string   

Trader's account number. Example: "8012345678"

reason   string   

Reason for withdrawal. Example: "Savings withdrawal"

pin   string   

Trader's transaction PIN if cash and agent's transaction PIN if transfer. Example: "1234"

Agents - Biometric Authentication

APIs for agent biometric authentication and device management

Enable biometric authentication for agent

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/biometric/enable" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"device_id\": \"dtitnxtvoexzynfxgmpix\",
    \"device_name\": \"w\",
    \"biometric_type\": \"fingerprint\",
    \"public_key\": \"fuga\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/biometric/enable"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "device_id": "dtitnxtvoexzynfxgmpix",
    "device_name": "w",
    "biometric_type": "fingerprint",
    "public_key": "fuga"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/agents/biometric/enable

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

device_id   string   

Must not be greater than 255 characters. Example: dtitnxtvoexzynfxgmpix

device_name   string  optional  

Must not be greater than 255 characters. Example: w

biometric_type   string   

Example: fingerprint

Must be one of:
  • fingerprint
  • face_id
  • both
public_key   string   

Example: fuga

Disable biometric authentication for current device

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/biometric/disable" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"device_id\": \"provlhwoxktutckjujpdqw\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/biometric/disable"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "device_id": "provlhwoxktutckjujpdqw"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/agents/biometric/disable

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

device_id   string   

Must not be greater than 255 characters. Example: provlhwoxktutckjujpdqw

Get all biometric devices for agent

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/agents/biometric/devices" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/agents/biometric/devices"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (403):

Show headers
cache-control: no-cache, private
content-type: application/json
vary: Origin
 

{
    "status": false,
    "message": "Unauthorize"
}
 

Request      

GET api/agents/biometric/devices

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Revoke biometric authentication for a device

Example request:
curl --request DELETE \
    "https://api.sabisave.com/api/agents/biometric/devices/praesentium" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/agents/biometric/devices/praesentium"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "DELETE",
    headers,
}).then(response => response.json());

Request      

DELETE api/agents/biometric/devices/{deviceId}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

deviceId   string   

Example: praesentium

Authenticate agent using biometric token

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/biometric/authenticate" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"biometric_token\": \"nesciunt\",
    \"device_id\": \"epqmgfxihets\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/biometric/authenticate"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "biometric_token": "nesciunt",
    "device_id": "epqmgfxihets"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/agents/biometric/authenticate

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

biometric_token   string   

Example: nesciunt

device_id   string   

Must not be greater than 255 characters. Example: epqmgfxihets

Banks

Get list of supported banks.

requires authentication

This endpoint returns a list of banks available for transactions. Requires Bearer Token Authentication.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/banks" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/banks"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2025-05-18T06:00:39.874949Z",
    "status": true,
    "message": "Banks",
    "data": {
        "success": true,
        "data": [
            {
                "id": 302,
                "name": "9mobile 9Payment Service Bank",
                "slug": "9mobile-9payment-service-bank-ng",
                "code": "120001",
                "longcode": "120001",
                "gateway": "",
                "pay_with_bank": false,
                "supports_transfer": true,
                "active": true,
                "country": "Nigeria",
                "currency": "NGN",
                "type": "nuban",
                "is_deleted": false,
                "createdAt": "2022-05-31T06:50:27.000Z",
                "updatedAt": "2022-06-23T09:33:55.000Z"
            },
            {
                "id": 174,
                "name": "Abbey Mortgage Bank",
                "slug": "abbey-mortgage-bank-ng",
                "code": "404",
                "longcode": "",
                "gateway": null,
                "pay_with_bank": false,
                "supports_transfer": true,
                "active": true,
                "country": "Nigeria",
                "currency": "NGN",
                "type": "nuban",
                "is_deleted": false,
                "createdAt": "2020-12-07T16:19:09.000Z",
                "updatedAt": "2023-09-14T13:02:38.000Z"
            }
        ]
    }
}
 

Example response (500):


{
    "message": "cURL Error #: <description>"
}
 

Request      

GET api/banks

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Beneficiaries

APIs for Beneficiary Authentication and Registration

Register a new beneficiary

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/v1/beneficiary/register" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"name\": \"John Doe\",
    \"email\": \"[email protected]\",
    \"phone\": \"08012345678\",
    \"nin\": \"12345678901\",
    \"account_number\": \"1234567890\",
    \"bank_name\": \"GTBank\",
    \"bank_code\": \"058\",
    \"address\": \"123 Main Street, Lagos\",
    \"average_yearly_income\": \"500000\",
    \"max_qualification\": \"Bachelor\'s Degree\",
    \"occupation\": \"Teacher\",
    \"password\": \"password123\",
    \"password_confirmation\": \"password123\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/v1/beneficiary/register"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "name": "John Doe",
    "email": "[email protected]",
    "phone": "08012345678",
    "nin": "12345678901",
    "account_number": "1234567890",
    "bank_name": "GTBank",
    "bank_code": "058",
    "address": "123 Main Street, Lagos",
    "average_yearly_income": "500000",
    "max_qualification": "Bachelor's Degree",
    "occupation": "Teacher",
    "password": "password123",
    "password_confirmation": "password123"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (201):


{
    "message": "Beneficiary registered successfully",
    "data": {
        "id": 1,
        "name": "John Doe",
        "email": "[email protected]",
        "phone": "08012345678",
        "nin": "12345678901",
        "account_number": "1234567890",
        "bank_name": "GTBank",
        "bank_code": "058",
        "address": "123 Main Street, Lagos",
        "status": "active",
        "token": "1|abc123def456..."
    }
}
 

Example response (422):


{
    "message": "Validation error",
    "details": {
        "phone": [
            "The phone has already been taken."
        ]
    }
}
 

Request      

POST api/admin/v1/beneficiary/register

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

name   string   

The full name of the beneficiary. Example: John Doe

email   string  optional  

optional The email address of the beneficiary. Example: [email protected]

phone   string   

The phone number of the beneficiary. Example: 08012345678

nin   string   

The National Identification Number. Example: 12345678901

account_number   string   

The bank account number. Example: 1234567890

bank_name   string   

The name of the bank. Example: GTBank

bank_code   string   

The bank code. Example: 058

address   string   

The residential address. Example: 123 Main Street, Lagos

average_yearly_income   numeric  optional  

optional Average yearly income in Naira. Example: 500000

max_qualification   string  optional  

optional Highest educational qualification. Example: Bachelor's Degree

occupation   string  optional  

optional Current occupation. Example: Teacher

password   string   

The password for the account. Example: password123

password_confirmation   string   

Password confirmation. Example: password123

Login a beneficiary

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/v1/beneficiary/login" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"phone\": \"08012345678\",
    \"password\": \"password123\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/v1/beneficiary/login"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "phone": "08012345678",
    "password": "password123"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Login successful",
    "data": {
        "beneficiary": {
            "id": 1,
            "name": "John Doe",
            "email": "[email protected]",
            "phone": "08012345678",
            "status": "active"
        },
        "token": "1|abc123def456..."
    }
}
 

Example response (401):


{
    "message": "Invalid credentials",
    "details": []
}
 

Request      

POST api/admin/v1/beneficiary/login

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

phone   string   

The phone number of the beneficiary. Example: 08012345678

password   string   

The password. Example: password123

Logout the authenticated beneficiary

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/v1/beneficiary/logout" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/v1/beneficiary/logout"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Logout successful"
}
 

Request      

POST api/admin/v1/beneficiary/logout

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Get authenticated beneficiary profile

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/v1/beneficiary/profile" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/v1/beneficiary/profile"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Profile retrieved successfully",
    "data": {
        "id": 1,
        "name": "John Doe",
        "email": "[email protected]",
        "phone": "08012345678",
        "nin": "12345678901",
        "account_number": "1234567890",
        "bank_name": "GTBank",
        "address": "123 Main Street, Lagos",
        "status": "active",
        "total_disbursed": "150000.00",
        "disbursements_count": 3
    }
}
 

Request      

GET api/admin/v1/beneficiary/profile

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Beneficiaries - Biometric Authentication

APIs for beneficiary biometric authentication and device management

Authenticate beneficiary using biometric token

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/v1/beneficiary/biometric/authenticate" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"biometric_token\": \"alias\",
    \"device_id\": \"hqwi\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/v1/beneficiary/biometric/authenticate"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "biometric_token": "alias",
    "device_id": "hqwi"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/admin/v1/beneficiary/biometric/authenticate

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

biometric_token   string   

Example: alias

device_id   string   

Must not be greater than 255 characters. Example: hqwi

Enable biometric authentication for beneficiary

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/v1/beneficiary/biometric/enable" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"device_id\": \"dhlrbsgmcoadymemwjomys\",
    \"device_name\": \"vicwknjqkidcswk\",
    \"biometric_type\": \"fingerprint\",
    \"public_key\": \"perferendis\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/v1/beneficiary/biometric/enable"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "device_id": "dhlrbsgmcoadymemwjomys",
    "device_name": "vicwknjqkidcswk",
    "biometric_type": "fingerprint",
    "public_key": "perferendis"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/admin/v1/beneficiary/biometric/enable

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

device_id   string   

Must not be greater than 255 characters. Example: dhlrbsgmcoadymemwjomys

device_name   string  optional  

Must not be greater than 255 characters. Example: vicwknjqkidcswk

biometric_type   string   

Example: fingerprint

Must be one of:
  • fingerprint
  • face_id
  • both
public_key   string   

Example: perferendis

Disable biometric authentication for current device

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/v1/beneficiary/biometric/disable" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"device_id\": \"kblanzxuzr\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/v1/beneficiary/biometric/disable"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "device_id": "kblanzxuzr"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/admin/v1/beneficiary/biometric/disable

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

device_id   string   

Must not be greater than 255 characters. Example: kblanzxuzr

Get all biometric devices for beneficiary

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/v1/beneficiary/biometric/devices" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/v1/beneficiary/biometric/devices"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (403):

Show headers
cache-control: no-cache, private
content-type: application/json
vary: Origin
 

{
    "status": false,
    "message": "Unauthorize"
}
 

Request      

GET api/admin/v1/beneficiary/biometric/devices

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Revoke biometric authentication for a device

Example request:
curl --request DELETE \
    "https://api.sabisave.com/api/admin/v1/beneficiary/biometric/devices/ut" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/v1/beneficiary/biometric/devices/ut"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "DELETE",
    headers,
}).then(response => response.json());

Request      

DELETE api/admin/v1/beneficiary/biometric/devices/{deviceId}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

deviceId   string   

Example: ut

Beneficiary - Phone Verification

APIs for Beneficiary Phone Number Verification

Send verification code to beneficiary's phone

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/v1/beneficiary/phone/send-verification" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"phone\": \"08012345678\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/v1/beneficiary/phone/send-verification"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "phone": "08012345678"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Verification code sent to your phone number",
    "data": {
        "phone": "08012345678",
        "expires_in_minutes": 10
    }
}
 

Example response (400):


{
    "message": "Beneficiary not found or account not active"
}
 

Example response (429):


{
    "message": "Please wait before requesting another code",
    "data": {
        "retry_after_minutes": 5
    }
}
 

Request      

POST api/admin/v1/beneficiary/phone/send-verification

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

phone   string   

The phone number to verify. Example: 08012345678

Verify phone number with OTP code

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/v1/beneficiary/phone/verify" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"phone\": \"08012345678\",
    \"otp\": \"1234\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/v1/beneficiary/phone/verify"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "phone": "08012345678",
    "otp": "1234"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Phone number verified successfully",
    "data": {
        "phone": "08012345678",
        "verified_at": "2024-01-01T12:00:00.000000Z"
    }
}
 

Example response (400):


{
    "message": "Invalid or expired verification code"
}
 

Request      

POST api/admin/v1/beneficiary/phone/verify

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

phone   string   

The phone number to verify. Example: 08012345678

otp   string   

The verification code received via SMS. Example: 1234

Check phone verification status

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/v1/beneficiary/phone/status" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"phone\": \"08012345678\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/v1/beneficiary/phone/status"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "phone": "08012345678"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Phone verification status retrieved",
    "data": {
        "phone": "08012345678",
        "is_verified": true,
        "verified_at": "2024-01-01T12:00:00.000000Z"
    }
}
 

Request      

POST api/admin/v1/beneficiary/phone/status

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

phone   string   

The phone number to check. Example: 08012345678

Resend verification code (protected route)

requires authentication

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/v1/beneficiary/phone/resend-verification" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/v1/beneficiary/phone/resend-verification"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Verification code sent to your phone number",
    "data": {
        "phone": "08012345678",
        "expires_in_minutes": 10
    }
}
 

Request      

POST api/admin/v1/beneficiary/phone/resend-verification

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Chat

APIs for chat conversations and messaging

Get all conversations for the authenticated agent.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/agent/chat/conversations" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/agent/chat/conversations"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Request      

GET api/agent/chat/conversations

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Get a specific conversation.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/agent/chat/conversations/delectus" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/agent/chat/conversations/delectus"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Request      

GET api/agent/chat/conversations/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the conversation. Example: delectus

Get messages for a conversation.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/agent/chat/conversations/veritatis/messages" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/agent/chat/conversations/veritatis/messages"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Request      

GET api/agent/chat/conversations/{id}/messages

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the conversation. Example: veritatis

Create a new conversation with an admin.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agent/chat/conversations" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"admin_id\": \"et\",
    \"title\": \"exuejyucmywrjmkeabwayak\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agent/chat/conversations"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "admin_id": "et",
    "title": "exuejyucmywrjmkeabwayak"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/agent/chat/conversations

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

admin_id   string   

Example: et

title   string  optional  

Must not be greater than 255 characters. Example: exuejyucmywrjmkeabwayak

Send a message in a conversation.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agent/chat/conversations/vel/messages" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"message\": \"nihil\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agent/chat/conversations/vel/messages"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "message": "nihil"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/agent/chat/conversations/{id}/messages

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the conversation. Example: vel

Body Parameters

message   string   

Example: nihil

attachments   object  optional  

Get all admins for starting a new conversation.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/agent/chat/admins" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/agent/chat/admins"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Request      

GET api/agent/chat/admins

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Country

Get Counteries

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/countries" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/countries"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "data": [
        {
            "id": 1,
            "name": "Country Name"
        },
        {
            "id": 2,
            "name": "Another Country"
        }
    ]
}
 

Request      

GET api/countries

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Endpoints

POST api/webhook/paystack

Example request:
curl --request POST \
    "https://api.sabisave.com/api/webhook/paystack" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/webhook/paystack"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Request      

POST api/webhook/paystack

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

POST api/webhook/9psb

Example request:
curl --request POST \
    "https://api.sabisave.com/api/webhook/9psb" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/webhook/9psb"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Request      

POST api/webhook/9psb

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Enable biometric authentication for trader

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/biometric/enable" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"device_id\": \"abc123def456\",
    \"device_name\": \"iPhone 13 Pro\",
    \"biometric_type\": \"fingerprint\",
    \"public_key\": \"-----BEGIN PUBLIC KEY-----...\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/biometric/enable"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "device_id": "abc123def456",
    "device_name": "iPhone 13 Pro",
    "biometric_type": "fingerprint",
    "public_key": "-----BEGIN PUBLIC KEY-----..."
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Biometric authentication enabled successfully",
    "data": {
        "device_id": "abc123def456",
        "biometric_token": "token123...",
        "biometric_type": "fingerprint",
        "enabled_at": "2024-01-01T12:00:00.000000Z"
    }
}
 

Request      

POST api/traders/biometric/enable

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

device_id   string   

Unique device identifier. Example: abc123def456

device_name   string  optional  

optional Human-readable device name. Example: iPhone 13 Pro

biometric_type   string   

Type of biometric. Example: fingerprint

public_key   string   

Device public key for encryption. Example: -----BEGIN PUBLIC KEY-----...

Disable biometric authentication for current device

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/biometric/disable" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"device_id\": \"abc123def456\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/biometric/disable"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "device_id": "abc123def456"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Biometric authentication disabled successfully"
}
 

Request      

POST api/traders/biometric/disable

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

device_id   string   

Device identifier to disable. Example: abc123def456

Get all biometric devices for trader

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/traders/biometric/devices" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/traders/biometric/devices"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Devices retrieved successfully",
    "data": [
        {
            "device_id": "abc123def456",
            "device_name": "iPhone 13 Pro",
            "biometric_type": "fingerprint",
            "is_enabled": true,
            "last_used_at": "2024-01-01T12:00:00.000000Z",
            "created_at": "2024-01-01T10:00:00.000000Z",
            "is_expired": false
        }
    ]
}
 

Request      

GET api/traders/biometric/devices

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Revoke biometric authentication for a device

Example request:
curl --request DELETE \
    "https://api.sabisave.com/api/traders/biometric/devices/sequi" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/traders/biometric/devices/sequi"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "DELETE",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Device revoked successfully"
}
 

Request      

DELETE api/traders/biometric/devices/{deviceId}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

deviceId   string   

Example: sequi

device_id   string   

Device identifier to revoke. Example: abc123def456

Authenticate trader using biometric token

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/biometric/authenticate" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"biometric_token\": \"token123...\",
    \"device_id\": \"abc123def456\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/biometric/authenticate"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "biometric_token": "token123...",
    "device_id": "abc123def456"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Authentication successful",
    "data": {
        "user": {
            "id": 1,
            "name": "John Doe",
            "phone": "08012345678"
        },
        "token": "1|abc123...",
        "device_id": "abc123def456",
        "authenticated_at": "2024-01-01T12:00:00.000000Z"
    }
}
 

Request      

POST api/traders/biometric/authenticate

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

biometric_token   string   

Biometric token from device. Example: token123...

device_id   string   

Device identifier. Example: abc123def456

Send a test notification to the authenticated admin

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/notifications/test" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/notifications/test"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Request      

POST api/admin/notifications/test

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Send a notification to all traders

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/notifications/notify-all-traders" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/notifications/notify-all-traders"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Request      

POST api/admin/notifications/notify-all-traders

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Send a notification to specific traders

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/notifications/notify-selected-traders" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/notifications/notify-selected-traders"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Request      

POST api/admin/notifications/notify-selected-traders

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Send a notification to a topic

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/notifications/notify-topic" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/notifications/notify-topic"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Request      

POST api/admin/notifications/notify-topic

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Guarantor

Create a new guarantor.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/guarantor" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"agent_id\": 1,
    \"gua1_relationship\": \"\\\"Father\\\"\",
    \"gua1_marital_status\": \"\\\"Married\\\"\",
    \"gua1_name\": \"\\\"John Doe\\\"\",
    \"gua1_phone_1\": \"\\\"08012345678\\\"\",
    \"gua1_phone_2\": \"\\\"08098765432\\\"\",
    \"gua1_work_category\": \"\\\"Employed\\\"\",
    \"gua1_work_address\": \"\\\"123 Street, Lagos\\\"\",
    \"gua1_place_of_work\": \"\\\"ABC Company\\\"\",
    \"gua2_relationship\": \"\\\"Mother\\\"\",
    \"gua2_marital_status\": \"\\\"Single\\\"\",
    \"gua2_name\": \"\\\"Jane Doe\\\"\",
    \"gua2_phone_1\": \"\\\"08011122233\\\"\",
    \"gua2_phone_2\": \"\\\"08033344455\\\"\",
    \"gua2_work_category\": \"\\\"Self-Employed\\\"\",
    \"gua2_work_address\": \"\\\"456 Street, Abuja\\\"\",
    \"gua2_place_of_work\": \"\\\"XYZ Enterprise\\\"\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/guarantor"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "agent_id": 1,
    "gua1_relationship": "\"Father\"",
    "gua1_marital_status": "\"Married\"",
    "gua1_name": "\"John Doe\"",
    "gua1_phone_1": "\"08012345678\"",
    "gua1_phone_2": "\"08098765432\"",
    "gua1_work_category": "\"Employed\"",
    "gua1_work_address": "\"123 Street, Lagos\"",
    "gua1_place_of_work": "\"ABC Company\"",
    "gua2_relationship": "\"Mother\"",
    "gua2_marital_status": "\"Single\"",
    "gua2_name": "\"Jane Doe\"",
    "gua2_phone_1": "\"08011122233\"",
    "gua2_phone_2": "\"08033344455\"",
    "gua2_work_category": "\"Self-Employed\"",
    "gua2_work_address": "\"456 Street, Abuja\"",
    "gua2_place_of_work": "\"XYZ Enterprise\""
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (201):


{
    "data": {
        "id": 1,
        "agent_id": 1,
        "gua1_relationship": "Father",
        "gua1_marital_status": "Married",
        "gua1_name": "John Doe",
        "gua1_phone_1": "08012345678",
        "gua1_phone_2": "08098765432",
        "gua1_work_category": "Employed",
        "gua1_work_address": "123 Street, Lagos",
        "gua1_place_of_work": "ABC Company",
        "gua2_relationship": "Mother",
        "gua2_marital_status": "Single",
        "gua2_name": "Jane Doe",
        "gua2_phone_1": "08011122233",
        "gua2_phone_2": "08033344455",
        "gua2_work_category": "Self-Employed",
        "gua2_work_address": "456 Street, Abuja",
        "gua2_place_of_work": "XYZ Enterprise"
    }
}
 

Example response (400):


{
    "message": "Invalid data sent",
    "details": {
        "agent_id": [
            "The agent_id field is required."
        ],
        "gua1_relationship": [
            "The gua1_relationship field is required."
        ]
    }
}
 

Request      

POST api/agents/guarantor

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

agent_id   integer   

The ID of the agent. Example: 1

gua1_relationship   string   

The relationship of the first guarantor. Example: "Father"

gua1_marital_status   string   

The marital status of the first guarantor. Example: "Married"

gua1_name   string   

The name of the first guarantor. Example: "John Doe"

gua1_phone_1   string   

The first phone number of the first guarantor. Example: "08012345678"

gua1_phone_2   string  optional  

nullable The second phone number of the first guarantor. Example: "08098765432"

gua1_work_category   string   

The work category of the first guarantor. Example: "Employed"

gua1_work_address   string   

The work address of the first guarantor. Example: "123 Street, Lagos"

gua1_place_of_work   string   

The place of work of the first guarantor. Example: "ABC Company"

gua2_relationship   string  optional  

nullable The relationship of the second guarantor. Example: "Mother"

gua2_marital_status   string  optional  

nullable The marital status of the second guarantor. Example: "Single"

gua2_name   string  optional  

nullable The name of the second guarantor. Example: "Jane Doe"

gua2_phone_1   string  optional  

nullable The first phone number of the second guarantor. Example: "08011122233"

gua2_phone_2   string  optional  

nullable The second phone number of the second guarantor. Example: "08033344455"

gua2_work_category   string  optional  

nullable The work category of the second guarantor. Example: "Self-Employed"

gua2_work_address   string  optional  

nullable The work address of the second guarantor. Example: "456 Street, Abuja"

gua2_place_of_work   string  optional  

nullable The place of work of the second guarantor. Example: "XYZ Enterprise"

Identity Verification

Verify BVN

requires authentication

Submit a user's BVN for verification.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/identity/bvn/verify" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"bvn\": \"12345678901\",
    \"first_name\": \"John\",
    \"last_name\": \"Doe\",
    \"date_of_birth\": \"1990-01-01\",
    \"phone\": \"08012345678\"
}"
const url = new URL(
    "https://api.sabisave.com/api/identity/bvn/verify"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "bvn": "12345678901",
    "first_name": "John",
    "last_name": "Doe",
    "date_of_birth": "1990-01-01",
    "phone": "08012345678"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "success": true,
    "message": "BVN verified successfully",
    "data": {
        "bvn": "12345678901",
        "first_name": "John",
        "last_name": "Doe"
    }
}
 

Example response (422):


{
    "success": false,
    "message": "BVN verification failed",
    "errors": {
        "detail": "Invalid BVN number"
    }
}
 

Request      

POST api/identity/bvn/verify

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

bvn   string   

The 11-digit BVN. Example: 12345678901

first_name   string  optional  

The user's first name. Example: John

last_name   string  optional  

The user's last name. Example: Doe

date_of_birth   string  optional  

The user's date of birth in YYYY-MM-DD format. Example: 1990-01-01

phone   string  optional  

The user's phone number. Example: 08012345678

Verify NIN

requires authentication

Submit a user's NIN for verification.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/identity/nin/verify" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"nin\": \"63184876213\",
    \"first_name\": \"Bunch\",
    \"last_name\": \"Dillon\",
    \"date_of_birth\": \"1990-01-01\",
    \"phone\": \"08000000000\"
}"
const url = new URL(
    "https://api.sabisave.com/api/identity/nin/verify"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "nin": "63184876213",
    "first_name": "Bunch",
    "last_name": "Dillon",
    "date_of_birth": "1990-01-01",
    "phone": "08000000000"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "success": true,
    "message": "NIN verified successfully",
    "data": {
        "nin": "63184876213",
        "first_name": "Bunch",
        "last_name": "Dillon"
    }
}
 

Example response (422):


{
    "success": false,
    "message": "NIN verification failed",
    "errors": {
        "detail": "Invalid NIN number"
    }
}
 

Request      

POST api/identity/nin/verify

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

nin   string   

The 11-digit NIN. Example: 63184876213

first_name   string  optional  

The user's first name. Example: Bunch

last_name   string  optional  

The user's last name. Example: Dillon

date_of_birth   string  optional  

The user's date of birth in YYYY-MM-DD format. Example: 1990-01-01

phone   string  optional  

The user's phone number. Example: 08000000000

Verify Address

requires authentication

Submit a user's address for verification.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/identity/address/verify" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"address\": \"123 Main Street, Ikeja\",
    \"state\": \"Lagos\",
    \"lga\": \"Ikeja\",
    \"landmark\": \"Near Shoprite\",
    \"last_name\": \"mhryawvcm\",
    \"first_name\": \"dnkvmhfjynvwntcce\",
    \"phone\": \"cyoqzkmjd\",
    \"city\": \"qpnbkihfamgkvjwnldhkvi\",
    \"candidate_name\": \"John Doe\",
    \"candidate_phone\": \"08012345678\"
}"
const url = new URL(
    "https://api.sabisave.com/api/identity/address/verify"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "address": "123 Main Street, Ikeja",
    "state": "Lagos",
    "lga": "Ikeja",
    "landmark": "Near Shoprite",
    "last_name": "mhryawvcm",
    "first_name": "dnkvmhfjynvwntcce",
    "phone": "cyoqzkmjd",
    "city": "qpnbkihfamgkvjwnldhkvi",
    "candidate_name": "John Doe",
    "candidate_phone": "08012345678"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "success": true,
    "message": "Address verified successfully",
    "data": {
        "address": "123 Main Street, Ikeja",
        "state": "Lagos",
        "verification_status": "verified"
    }
}
 

Example response (422):


{
    "success": false,
    "message": "Address verification failed"
}
 

Request      

POST api/identity/address/verify

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

address   string   

The full address (max 500 chars). Example: 123 Main Street, Ikeja

state   string  optional  

The state (max 100 chars). Example: Lagos

lga   string  optional  

The LGA (max 100 chars). Example: Ikeja

landmark   string  optional  

A nearby landmark (max 255 chars). Example: Near Shoprite

last_name   string  optional  

Must not be greater than 255 characters. Example: mhryawvcm

first_name   string  optional  

Must not be greater than 255 characters. Example: dnkvmhfjynvwntcce

phone   string  optional  

Must not be greater than 20 characters. Example: cyoqzkmjd

city   string   

Must not be greater than 100 characters. Example: qpnbkihfamgkvjwnldhkvi

candidate_name   string  optional  

The candidate name (max 255 chars). Example: John Doe

candidate_phone   string  optional  

The candidate phone (max 20 chars). Example: 08012345678

Verify Utility Bill

requires authentication

Submit a user's utility bill for verification.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/identity/utility-bill/verify" \
    --header "Content-Type: multipart/form-data" \
    --header "Accept: application/json" \
    --form "bill_type=electricity"\
    --form "account_number=1234567890"\
    --form "address=123 Main Street"\
    --form "bill_image=@/tmp/phpxssChf" 
const url = new URL(
    "https://api.sabisave.com/api/identity/utility-bill/verify"
);

const headers = {
    "Content-Type": "multipart/form-data",
    "Accept": "application/json",
};

const body = new FormData();
body.append('bill_type', 'electricity');
body.append('account_number', '1234567890');
body.append('address', '123 Main Street');
body.append('bill_image', document.querySelector('input[name="bill_image"]').files[0]);

fetch(url, {
    method: "POST",
    headers,
    body,
}).then(response => response.json());

Example response (200):


{
    "success": true,
    "message": "Utility bill verified successfully",
    "data": {
        "bill_type": "electricity",
        "verified": true
    }
}
 

Example response (422):


{
    "success": false,
    "message": "Utility bill verification failed"
}
 

Request      

POST api/identity/utility-bill/verify

Headers

Content-Type      

Example: multipart/form-data

Accept      

Example: application/json

Body Parameters

bill_type   string   

The bill type. Must be one of electricity, water, gas, internet, cable. Example: electricity

bill_image   file   

The bill image file (jpeg, png, gif, or pdf). Example: /tmp/phpxssChf

account_number   string  optional  

The account number (max 100 chars). Example: 1234567890

address   string  optional  

The address (max 500 chars). Example: 123 Main Street

Get verification status

requires authentication

Retrieve the user's current identity verification statuses.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/identity/status" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/identity/status"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "success": true,
    "data": {
        "bvn_verified": true,
        "bvn_verified_at": "2025-11-01T01:30:00.000000Z",
        "nin_verified": true,
        "nin_verified_at": "2025-11-01T01:35:00.000000Z",
        "address_verified": false,
        "address_verified_at": null,
        "utility_bill_verified": false,
        "utility_bill_verified_at": null,
        "identity_verified": true
    }
}
 

Request      

GET api/identity/status

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

LGA

Get Local Government Area

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/lgas?country_id=1&state_id=1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/lgas"
);

const params = {
    "country_id": "1",
    "state_id": "1",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "data": [
        {
            "id": 1,
            "name": "Lga Name",
            "state_id": "1",
            "country_id": "1"
        },
        {
            "id": 2,
            "name": "Another Lga",
            "state_id": "1",
            "country_id": "1"
        }
    ]
}
 

Example response (500):


{
    "message": "An error occurred",
    "data": [],
    "statusCode": 500
}
 

Request      

GET api/lgas

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Query Parameters

country_id   integer  optional  

(optional)string The ID of the country. Example: 1

state_id   string  optional  

(optional)string The ID of the state. Example: 1

Notifications

APIs for notification management

Register a device token for push notifications

Example request:
curl --request POST \
    "https://api.sabisave.com/api/notifications/register-token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"token\": \"wmzrrphnzwtpwwrsw\",
    \"device_type\": \"ios\"
}"
const url = new URL(
    "https://api.sabisave.com/api/notifications/register-token"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "token": "wmzrrphnzwtpwwrsw",
    "device_type": "ios"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/notifications/register-token

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

token   string   

Must not be greater than 255 characters. Example: wmzrrphnzwtpwwrsw

device_type   string   

Example: ios

Must be one of:
  • android
  • ios
  • web

Unregister a device token

Example request:
curl --request POST \
    "https://api.sabisave.com/api/notifications/unregister-token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"token\": \"fxwkzr\"
}"
const url = new URL(
    "https://api.sabisave.com/api/notifications/unregister-token"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "token": "fxwkzr"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/notifications/unregister-token

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

token   string   

Must not be greater than 255 characters. Example: fxwkzr

Get notification settings

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/notifications/settings" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/notifications/settings"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (403):

Show headers
cache-control: no-cache, private
content-type: application/json
vary: Origin
 

{
    "status": false,
    "message": "Unauthorize"
}
 

Request      

GET api/notifications/settings

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Update notification settings

Example request:
curl --request POST \
    "https://api.sabisave.com/api/notifications/settings" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"general_notifications\": false,
    \"payment_notifications\": false,
    \"system_notifications\": false
}"
const url = new URL(
    "https://api.sabisave.com/api/notifications/settings"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "general_notifications": false,
    "payment_notifications": false,
    "system_notifications": false
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/notifications/settings

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

general_notifications   boolean  optional  

Example: false

payment_notifications   boolean  optional  

Example: false

system_notifications   boolean  optional  

Example: false

Save an FCM token for the authenticated user <aside class="notice">This API endpoint is only accessible by authenticated users.</aside>

requires authentication

Example request:
curl --request POST \
    "https://api.sabisave.com/api/notifications/fcm-token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"fcm_token\": \"quidem\"
}"
const url = new URL(
    "https://api.sabisave.com/api/notifications/fcm-token"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "fcm_token": "quidem"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200, success):


{
    "message": "FCM token saved successfully."
}
 

Example response (401, unauthenticated):


{
    "error": "User not authenticated"
}
 

Example response (422, validation_error):


{
    "error": "The fcm token field is required."
}
 

Request      

POST api/notifications/fcm-token

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

fcm_token   string   

Example: quidem

Get all notifications for the authenticated user

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/notifications" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/notifications"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (403):

Show headers
cache-control: no-cache, private
content-type: application/json
vary: Origin
 

{
    "status": false,
    "message": "Unauthorize"
}
 

Request      

GET api/notifications

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Get unread notification count

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/notifications/unread-count" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/notifications/unread-count"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (403):

Show headers
cache-control: no-cache, private
content-type: application/json
vary: Origin
 

{
    "status": false,
    "message": "Unauthorize"
}
 

Request      

GET api/notifications/unread-count

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Mark a notification as read

Example request:
curl --request POST \
    "https://api.sabisave.com/api/notifications/et/read" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/notifications/et/read"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Request      

POST api/notifications/{id}/read

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the notification. Example: et

Mark all notifications as read

Example request:
curl --request POST \
    "https://api.sabisave.com/api/notifications/read-all" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/notifications/read-all"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Request      

POST api/notifications/read-all

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Delete a notification

Example request:
curl --request DELETE \
    "https://api.sabisave.com/api/notifications/dolore" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/notifications/dolore"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "DELETE",
    headers,
}).then(response => response.json());

Request      

DELETE api/notifications/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the notification. Example: dolore

OAuth

APIs for OAuth token refresh

Refreshes an existing token.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/auth/refresh-token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"refresh_token\": \"\\\"your_refresh_token_here\\\"\"
}"
const url = new URL(
    "https://api.sabisave.com/api/auth/refresh-token"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "refresh_token": "\"your_refresh_token_here\""
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "status": 1,
    "message": "Successfully refreshed token",
    "token": "your_new_token_here",
    "refresh_token": "your_new_refresh_token_here",
    "expire_at": "dd-mm-yy HH:mm:ss",
    "token_type": "Bearer"
}
 

Example response (400):


{
    "status": 0,
    "message": {
        "refresh_token": [
            "The refresh token is required.",
            "The refresh token must be at least 6 characters."
        ]
    }
}
 

Example response (403):


{
    "status": 0,
    "message": "Refresh token expired"
}
 

Example response (404):


{
    "status": 0,
    "message": "Refresh Token does not exist"
}
 

Request      

POST api/auth/refresh-token

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

refresh_token   string   

The refresh token to be used for token refresh. Example: "your_refresh_token_here"

State

Get all State

Get state by country id .

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/states" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/states"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (201):


{
    "data": {
        "id": 4,
        "name": "State Name",
        "country_id": "1"
    }
}
 

Example response (422):


{
    "message": "Invalid data sent",
    "details": {
        "country_id": [
            "The country_id field is required."
        ]
    }
}
 

Request      

GET api/states

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

country_id   string  optional  

The ID of the country. Example: 1

Trader

Get the balance of the authenticated trader.

requires authentication

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/traders/balance" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/traders/balance"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "balance": 1000
}
 

Example response (404):


{
    "message": "Trader not found"
}
 

Request      

GET api/traders/balance

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Get a single transaction of the authenticated trader.

requires authentication

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/traders/transactions/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/traders/transactions/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
  "id": 5,
  "amount": 230000,
  "type": "deposit",
  "trader": {
    "id": 1,
    "phone": "08132221963",
    "full_name": "Super Admin",
    "other_name": null,
    "email": "[email protected]",
    "dob": "2009-07-18",
    "gender": "male",
    "has_cooperative": true,
    "cooperative": "Aufderhar, Olson and Boehm",
    "username": "super-admin",
    "balance": 1150000,
    "account_number": "8139060545",
    "bank_details": {
      "id": 17,
      "bank_name": "Zenith Bank",
      "account_type": "savings",
      "account_number": "7102866199",
      "bank_code": "812"
    },
    "created_at": "2025-05-28 19:54:26",
    "updated_at": "2025-05-28 19:54:26"
  },
  "recipient": "trader",
  "status": "completed",
  "agent": {
    "id": 1,
    "trader_union": "aspernatur",
    "email": "[email protected]",
    "username": "super-admin",
    "first_name": "Super",
    "last_name": "Admin",
    "phone": "08132221963",
    "gender": "female",
    "dob": "2011-09-06T00:00:00.000000Z",
    "country": "Nigeria",
    "state": "Akwa Ibom State",
    "lga": "Essien Udim",
    "address": "6801 Kuhn Path\nPort Mittie, SD 68269-5146",
    "post_code": "57378",
    "profile": "https://via.placeholder.com/640x480.png/002266?text=quisquam",
    "agent_number": "08132221963",
    "balance": 1150000,
    "bank_details": {
      "id": 1,
      "bank_name": "GTB",
      "account_type": "savings",
      "account_number": "4560815",
      "bank_code": "058"
    }
  },
  "created_at": "2025-06-03 10:36:00",
  "updated_at": "2025-06-03 10:36:00",
  "reference": null
 

Request      

GET api/traders/transactions/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the transaction. Example: 1

Trader Management

List all traders

requires authentication

Retrieves a paginated list of all traders along with summary statistics, trader status overview, savings plans overview, and monthly analytics data.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/traders?page=1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/traders"
);

const params = {
    "page": "1",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Traders data retrieved successfully",
    "data": {
        "summary": {
            "total_savings": 500000,
            "total_withdrawals": 200000,
            "earned_interest": 40000,
            "total_traders": 50
        },
        "traders_overview": {
            "total": 50,
            "active": 45,
            "inactive": 5,
            "active_percentage": 90,
            "inactive_percentage": 10
        },
        "savings_plans_overview": {
            "daily": 30,
            "weekly": 20
        },
        "analytics": {
            "labels": [
                "Jan",
                "Feb",
                "Mar",
                "Apr",
                "May",
                "Jun",
                "Jul",
                "Aug",
                "Sep",
                "Oct",
                "Nov",
                "Dec"
            ],
            "datasets": [
                {
                    "label": "Deposits",
                    "data": [
                        10000,
                        15000,
                        20000,
                        25000,
                        30000,
                        35000,
                        40000,
                        45000,
                        50000,
                        55000,
                        60000,
                        65000
                    ],
                    "backgroundColor": "#F6C000"
                },
                {
                    "label": "Withdrawals",
                    "data": [
                        5000,
                        7500,
                        10000,
                        12500,
                        15000,
                        17500,
                        20000,
                        22500,
                        25000,
                        27500,
                        30000,
                        32500
                    ],
                    "backgroundColor": "#000000"
                }
            ]
        },
        "traders": {
            "data": [
                {
                    "id": 1,
                    "first_name": "John",
                    "last_name": "Doe",
                    "email": "[email protected]",
                    "phone": "+1234567890",
                    "status": {
                        "id": 1,
                        "name": "active"
                    },
                    "location": {
                        "country": "Nigeria",
                        "state": "Lagos",
                        "lga": "Ikeja"
                    },
                    "created_at": "2023-01-01T12:00:00.000000Z"
                }
            ],
            "links": {
                "first": "http://example.com/api/admin/traders?page=1",
                "last": "http://example.com/api/admin/traders?page=5",
                "prev": null,
                "next": "http://example.com/api/admin/traders?page=2"
            },
            "meta": {
                "current_page": 1,
                "from": 1,
                "last_page": 5,
                "path": "http://example.com/api/admin/traders",
                "per_page": 10,
                "to": 10,
                "total": 50
            }
        }
    }
}
 

Example response (500):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Internal server error",
    "data": null
}
 

Request      

GET api/admin/traders

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Query Parameters

page   integer  optional  

Page number for pagination. Example: 1

requires authentication

Searches for traders by name, email, phone, or location.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/traders/search?search=John" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/traders/search"
);

const params = {
    "search": "John",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Traders found",
    "data": {
        "traders": {
            "current_page": 1,
            "data": [
                {
                    "id": 1,
                    "name": "John Doe",
                    "email": "[email protected]",
                    "phone": "+1234567890",
                    "status": {
                        "id": 1,
                        "name": "active"
                    },
                    "location": {
                        "country": "Nigeria",
                        "state": "Lagos",
                        "lga": "Ikeja"
                    }
                }
            ],
            "first_page_url": "http://example.com/api/admin/traders?page=1",
            "from": 1,
            "last_page": 5,
            "last_page_url": "http://example.com/api/admin/traders?page=5",
            "links": [],
            "next_page_url": "http://example.com/api/admin/traders?page=2",
            "path": "http://example.com/api/admin/traders",
            "per_page": 10,
            "prev_page_url": null,
            "to": 10,
            "total": 50
        }
    }
}
 

Get trader details

requires authentication

Retrieves detailed information about a specific trader including their personal details, financial summary, savings plan, and transaction history.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/traders/trader/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/traders/trader/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Trader details retrieved successfully",
    "data": {
        "trader": {
            "id": 1,
            "first_name": "John",
            "last_name": "Doe",
            "email": "[email protected]",
            "phone": "+1234567890",
            "status": {
                "id": 1,
                "name": "active"
            },
            "location": {
                "country": "Nigeria",
                "state": "Lagos",
                "lga": "Ikeja",
                "address": "123 Main Street"
            },
            "business_details": {
                "business_name": "Example Business",
                "business_type": "Retail",
                "business_address": "456 Market Street"
            },
            "bank_details": {
                "bank_name": "Example Bank",
                "account_number": "1234567890",
                "account_name": "John Doe"
            },
            "identification": {
                "id_type": "National ID",
                "id_number": "ID12345678",
                "id_image": "identifications/id.jpg"
            },
            "created_at": "2023-01-01T12:00:00.000000Z",
            "updated_at": "2023-01-01T12:00:00.000000Z"
        },
        "financial_summary": {
            "balance": 50000,
            "total_deposits": 100000,
            "total_withdrawals": 50000,
            "earned_interest": 0
        },
        "savings_plan": {
            "id": 1,
            "frequency": "daily",
            "amount": 1000,
            "start_date": "2023-01-01",
            "end_date": "2023-12-31",
            "status": "active"
        },
        "transactions": {
            "data": [
                {
                    "id": 1,
                    "type": "deposit",
                    "amount": 10000,
                    "status": {
                        "id": 1,
                        "name": "completed"
                    },
                    "created_at": "2023-01-01T12:00:00.000000Z"
                }
            ],
            "links": {
                "first": "http://example.com/api/admin/traders/1?page=1",
                "last": "http://example.com/api/admin/traders/1?page=1",
                "prev": null,
                "next": null
            },
            "meta": {
                "current_page": 1,
                "from": 1,
                "last_page": 1,
                "path": "http://example.com/api/admin/traders/1",
                "per_page": 10,
                "to": 1,
                "total": 1
            }
        }
    }
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Trader not found",
    "data": null
}
 

Request      

GET api/admin/traders/trader/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the trader. Example: 1

Toggle trader status

requires authentication

Blocks or unblocks a trader account. When blocked, the trader cannot access the system or perform any transactions.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/admin/traders/1/toggle-block" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"reason\": \"Suspicious activity detected\"
}"
const url = new URL(
    "https://api.sabisave.com/api/admin/traders/1/toggle-block"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "reason": "Suspicious activity detected"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200, Blocked):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Trader blocked successfully",
    "data": {
        "id": 1,
        "first_name": "John",
        "last_name": "Doe",
        "status": {
            "id": 2,
            "name": "inactive"
        },
        "block_reason": "Suspicious activity detected",
        "updated_at": "2023-01-01T12:00:00.000000Z"
    }
}
 

Example response (200, Unblocked):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Trader unblocked successfully",
    "data": {
        "id": 1,
        "first_name": "John",
        "last_name": "Doe",
        "status": {
            "id": 1,
            "name": "active"
        },
        "block_reason": null,
        "updated_at": "2023-01-01T12:00:00.000000Z"
    }
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Trader not found",
    "data": null
}
 

Request      

POST api/admin/traders/{id}/toggle-block

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the trader. Example: 1

Body Parameters

reason   string   

Reason for blocking/unblocking the trader. Example: Suspicious activity detected

Delete trader

requires authentication

Permanently deletes a trader account and all associated data. This action cannot be undone.

Example request:
curl --request DELETE \
    "https://api.sabisave.com/api/admin/traders/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/traders/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "DELETE",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Trader deleted successfully",
    "data": null
}
 

Example response (400):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Cannot delete trader with active balance",
    "data": null
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Trader not found",
    "data": null
}
 

Request      

DELETE api/admin/traders/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the trader. Example: 1

Trader Transactions

Display a listing of the resource.

requires authentication

Retrieves a paginated list of transactions for the authenticated trader.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/traders/transactions" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/traders/transactions"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "data": [
        {
            "id": 5,
            "amount": 230000,
            "type": "deposit",
            "trader": {
                "id": 1,
                "phone": "08132221963",
                "full_name": "Super Admin",
                "other_name": null,
                "email": "[email protected]",
                "dob": "2009-07-18",
                "gender": "male",
                "has_cooperative": true,
                "cooperative": "Aufderhar, Olson and Boehm",
                "username": "super-admin",
                "balance": 1150000,
                "account_number": "8139060545",
                "bank_details": {
                    "id": 17,
                    "bank_name": "Zenith Bank",
                    "account_type": "savings",
                    "account_number": "7102866199",
                    "bank_code": "812"
                },
                "created_at": "2025-05-28 19:54:26",
                "updated_at": "2025-05-28 19:54:26"
            },
            "recipient": "trader",
            "status": "completed",
            "agent": {
                "id": 1,
                "trader_union": "aspernatur",
                "email": "[email protected]",
                "username": "super-admin",
                "first_name": "Super",
                "last_name": "Admin",
                "phone": "08132221963",
                "gender": "female",
                "dob": "2011-09-06T00:00:00.000000Z",
                "country": "Nigeria",
                "state": "Akwa Ibom State",
                "lga": "Essien Udim",
                "address": "6801 Kuhn Path\nPort Mittie, SD 68269-5146",
                "post_code": "57378",
                "profile": "https://via.placeholder.com/640x480.png/002266?text=quisquam",
                "agent_number": "08132221963",
                "balance": 1150000,
                "bank_details": {
                    "id": 1,
                    "bank_name": "GTB",
                    "account_type": "savings",
                    "account_number": "4560815",
                    "bank_code": "058"
                }
            },
            "created_at": "2025-06-03 10:36:00",
            "updated_at": "2025-06-03 10:36:00",
            "reference": null
        }
    ],
    "links": {
        "first": "http://example.com?page=1",
        "last": "http://example.com?page=10",
        "prev": null,
        "next": "http://example.com?page=2"
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 10,
        "path": "http://example.com",
        "per_page": 25,
        "to": 25,
        "total": 250
    }
}
 

Request      

GET api/traders/transactions

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

List trader transactions

requires authentication

Retrieves a paginated list of trader transactions with optional filtering by trader ID, date range, transaction type, and status.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/traders/transactions?trader_id=1&start_date=2023-01-01&end_date=2023-12-31&type=deposit&status_id=1&page=1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/traders/transactions"
);

const params = {
    "trader_id": "1",
    "start_date": "2023-01-01",
    "end_date": "2023-12-31",
    "type": "deposit",
    "status_id": "1",
    "page": "1",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Transactions retrieved successfully",
    "data": {
        "transactions": {
            "current_page": 1,
            "data": [
                {
                    "id": 1,
                    "trader": {
                        "id": 1,
                        "name": "John Doe"
                    },
                    "type": "deposit",
                    "amount": 10000,
                    "status": {
                        "id": 1,
                        "name": "completed"
                    },
                    "created_at": "2023-01-01T12:00:00.000000Z"
                }
            ],
            "first_page_url": "http://example.com/api/admin/traders/transactions?page=1",
            "from": 1,
            "last_page": 5,
            "last_page_url": "http://example.com/api/admin/traders/transactions?page=5",
            "links": [],
            "next_page_url": "http://example.com/api/admin/traders/transactions?page=2",
            "path": "http://example.com/api/admin/traders/transactions",
            "per_page": 10,
            "prev_page_url": null,
            "to": 10,
            "total": 50
        },
        "summary": {
            "total_amount": 500000,
            "total_count": 50
        }
    }
}
 

Example response (500):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Internal server error",
    "data": null
}
 

Request      

GET api/admin/traders/transactions

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Query Parameters

trader_id   integer  optional  

ID of the trader to filter transactions. Example: 1

start_date   string  optional  

date Start date for filtering transactions (YYYY-MM-DD). Example: 2023-01-01

end_date   string  optional  

date End date for filtering transactions (YYYY-MM-DD). Example: 2023-12-31

type   string  optional  

Transaction type (deposit/withdrawal). Example: deposit

status_id   integer  optional  

Status ID for filtering transactions. Example: 1

page   integer  optional  

Page number for pagination. Example: 1

Traders

APIs for Traders

update trader address details

Example request:
curl --request POST \
    "https://api.sabisave.com/api/address/update" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"country_id\": \"1\",
    \"state_id\": \"1\",
    \"lga_id\": \"1\",
    \"address\": \"\\\"123 Street, City, State\\\"\",
    \"post_code\": \"\\\"100001\\\"\"
}"
const url = new URL(
    "https://api.sabisave.com/api/address/update"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "country_id": "1",
    "state_id": "1",
    "lga_id": "1",
    "address": "\"123 Street, City, State\"",
    "post_code": "\"100001\""
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (114):


{
    "message": "address details update failed",
    "details": []
}
 

Example response (200):


{
    "message": "Trader step 2 registration completed",
    "data": {
        "country_id": "1",
        "state_id": "1",
        "lga_id": "1",
        "address": "abuja",
        "post_code": "1234"
    }
}
 

Example response (404):


{
    "message": "not found ",
    "details": []
}
 

Request      

POST api/address/update

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

country_id   numeric   

The ID of the country. Example: 1

state_id   numeric   

The ID of the state. Example: 1

lga_id   numeric   

The ID of the local government area. Example: 1

address   string   

The address of the agent. Example: "123 Street, City, State"

post_code   string   

The postal code of the agent's address. Example: "100001"

Trader Login.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/login" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"phone\": \"08013221673\",
    \"pin\": \"1234\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/login"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "phone": "08013221673",
    "pin": "1234"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
  "status": 1,
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
  "refresh_token": "def50200ea86c5d6161c...",
  "expire_at": "29-06-24 14:57:10",
  "token_type": "Bearer",
  "message": "Successfully logged in",
  "trader": {
      "id": 1,
      "name": "John Doe",
      "email": "[email protected]",
      ...
  }
}
 

Example response (422):


{
    "message": "Invalid data sent",
    "details": {
        "phone": [
            "phone field is required."
        ],
        "pin": [
            "The pin must be at least 4 characters."
        ]
    }
}
 

Request      

POST api/traders/login

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

phone   string   

The agent number of the agent. Example: 08013221673

pin   string   

The pin of the agent. Minimum and maximum length of 4 characters. Example: 1234

Verify a bank account

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/bank-details/verify" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"account_number\": \"1234567890\",
    \"bank_code\": \"058\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/bank-details/verify"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "account_number": "1234567890",
    "bank_code": "058"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Account verified successfully",
    "data": {
        "account_number": "1234567890",
        "account_name": "John Doe",
        "bank_id": 1
    }
}
 

Example response (400):


{
    "message": "Could not verify account",
    "details": []
}
 

Request      

POST api/traders/bank-details/verify

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

account_number   string   

The account number. Example: 1234567890

bank_code   string   

The bank code. Example: 058

Get list of banks from Paystack

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/traders/bank-details/banks-list" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/traders/bank-details/banks-list"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Banks retrieved successfully",
    "data": [
        {
            "id": 1,
            "name": "Access Bank",
            "slug": "access-bank",
            "code": "044",
            "longcode": "044150149",
            "gateway": "emandate",
            "pay_with_bank": true,
            "active": true,
            "country": "Nigeria",
            "currency": "NGN",
            "type": "nuban",
            "is_deleted": false,
            "createdAt": "2016-07-14T10:04:29.000Z",
            "updatedAt": "2020-02-18T08:06:44.000Z"
        }
    ]
}
 

Request      

GET api/traders/bank-details/banks-list

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Trader pin confirmation .

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/confirm/pin" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"pin\": \"1234\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/confirm/pin"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "pin": "1234"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
  "message": "trader pin confirmed",

}
 

Example response (404):


{
  "message": "trader not found",
  "details": []
}
 @response 500 {
  "message": "internal server error",
  "details": []
}
 

Request      

POST api/traders/confirm/pin

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

pin   numeric  optional  

required. Minimum and maximum length of 4 characters.. Example: 1234

Verify phone number with OTP for PIN change

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/reset-pin/send-otp" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"phone\": \"09031922234\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/reset-pin/send-otp"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "phone": "09031922234"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "OTP sent to your phone number",
    "data": {
        "phone": "09031922234"
    }
}
 

Example response (404):


{
    "message": "Trader not found",
    "details": []
}
 

Request      

POST api/traders/reset-pin/send-otp

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

phone   string   

The phone number of the trader. Example: 09031922234

Create new PIN after verification

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/reset-pin/create-new-pin" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"phone\": \"09031922234\",
    \"otp\": \"123456\",
    \"pin\": \"1234\",
    \"pin_confirmation\": \"1234\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/reset-pin/create-new-pin"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "phone": "09031922234",
    "otp": "123456",
    "pin": "1234",
    "pin_confirmation": "1234"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "PIN changed successfully",
    "data": {
        "success": true
    }
}
 

Example response (404):


{
    "message": "Trader not found",
    "details": []
}
 

Request      

POST api/traders/reset-pin/create-new-pin

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

phone   string   

The phone number of the trader. Example: 09031922234

otp   string   

The OTP received on the phone. Example: 123456

pin   numeric   

Minimum and maximum length of 4 characters. Example: 1234

pin_confirmation   same  optional  

with pin. Example: 1234

POST api/traders/bankdetails/update

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/bankdetails/update" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"bank_name\": \"GTB\",
    \"account_type\": \"savings\",
    \"account_number\": \"1234567890\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/bankdetails/update"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "bank_name": "GTB",
    "account_type": "savings",
    "account_number": "1234567890"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (114):


{
    "message": "bank details update failed",
    "details": []
}
 

Example response (200):


{
  "message": "Trader step 2 registration completed",
  "data": {
      "bank_name": "GTB",
      "account_type": "savings",
      "account_number": "1234567890",
      "trader_id": 1,
  }
}
 

Example response (404):


{
    "message": "not found ",
    "details": []
}
 

Request      

POST api/traders/bankdetails/update

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

bank_name   string.  optional  

name of traders bank. Example: GTB

account_type   enum   

Enum('savings','current') ........ Example: savings

account_number   strinng   

The account number of trader. Example: 1234567890

update trader address details

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/address/update" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"country_id\": \"1\",
    \"state_id\": \"1\",
    \"lga_id\": \"1\",
    \"address\": \"\\\"123 Street, City, State\\\"\",
    \"post_code\": \"\\\"100001\\\"\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/address/update"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "country_id": "1",
    "state_id": "1",
    "lga_id": "1",
    "address": "\"123 Street, City, State\"",
    "post_code": "\"100001\""
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (114):


{
    "message": "address details update failed",
    "details": []
}
 

Example response (200):


{
    "message": "Trader step 2 registration completed",
    "data": {
        "country_id": "1",
        "state_id": "1",
        "lga_id": "1",
        "address": "abuja",
        "post_code": "1234"
    }
}
 

Example response (404):


{
    "message": "not found ",
    "details": []
}
 

Request      

POST api/traders/address/update

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

country_id   numeric   

The ID of the country. Example: 1

state_id   numeric   

The ID of the state. Example: 1

lga_id   numeric   

The ID of the local government area. Example: 1

address   string   

The address of the agent. Example: "123 Street, City, State"

post_code   string   

The postal code of the agent's address. Example: "100001"

Initiate Trader PIN reset by phone number.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/reset-pin/initiate" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"phone\": \"09031922234\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/reset-pin/initiate"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "phone": "09031922234"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "OTP sent to your phone number",
    "data": {
        "phone": "09031922234"
    }
}
 

Example response (404):


{
    "message": "trader not found",
    "details": []
}
 

Request      

POST api/traders/reset-pin/initiate

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

phone   string   

The phone number of the trader. Example: 09031922234

Complete Trader pin reset.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/reset-pin/complete" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"phone\": \"09031922234\",
    \"otp\": \"123456\",
    \"pin\": \"1234\",
    \"pin_confirmation\": \"1234\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/reset-pin/complete"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "phone": "09031922234",
    "otp": "123456",
    "pin": "1234",
    "pin_confirmation": "1234"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (114):


{
    "message": "pin update failed",
    "details": []
}
 

Example response (200):


{
    "message": "PIN changed successfully",
    "data": {
        "success": true
    }
}
 

Example response (404):


{
    "message": "trader not found",
    "details": []
}
 

Example response (500):


{
    "message": "internal server error",
    "details": []
}
 

Request      

POST api/traders/reset-pin/complete

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

phone   string   

The phone number of the trader. Example: 09031922234

otp   string   

The OTP received on the phone. Example: 123456

pin   numeric   

.Minimum and maximum length of 4 characters.. Example: 1234

pin_confirmation   same  optional  

with pin . Example: 1234

Logout trader

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/logout" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/traders/logout"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Successfully logged out",
    "data": {
        "success": true
    }
}
 

Request      

POST api/traders/logout

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Delete trader

requires authentication

Permanently deletes a trader account and all associated data. This action cannot be undone.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/delete-account/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/traders/delete-account/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Trader deleted successfully",
    "data": null
}
 

Example response (400):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Cannot delete trader with active balance",
    "data": null
}
 

Example response (404):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Trader not found",
    "data": null
}
 

Request      

POST api/traders/delete-account/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the trader. Example: 1

Get trader's bank details

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/traders/banks" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/traders/banks"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Bank details retrieved successfully",
    "data": [
        {
            "id": 1,
            "bank_name": "GTB",
            "account_type": "savings",
            "account_number": "1234567890",
            "bank_code": "058"
        }
    ]
}
 

Request      

GET api/traders/banks

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Get trader profile

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/traders/profile" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/traders/profile"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Profile retrieved successfully",
    "data": {
        "id": 1,
        "full_name": "Ibraheem Razaq",
        "email": "[email protected]",
        "phone": "+2348016067",
        "gender": "Male",
        "dob": "12/08/1990",
        "address": "No 18 Allen Str Ikeja",
        "customer_id": "802430840",
        "trader_level": "Silver Level",
        "account_status": "verified",
        "saving_plan": "Daily Saving Plan",
        "profile_image": "/storage/profile/image.jpg"
    }
}
 

Request      

GET api/traders/profile

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Update trader profile information

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/profile/update" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"address\": \"No 18 Allen Str Ikeja\",
    \"gender\": \"Male\",
    \"email\": \"[email protected]\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/profile/update"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "address": "No 18 Allen Str Ikeja",
    "gender": "Male",
    "email": "[email protected]"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Profile updated successfully",
    "data": {
        "id": 1,
        "full_name": "Ibraheem Razaq",
        "email": "[email protected]",
        "phone": "+2348016067",
        "gender": "Male",
        "dob": "12/08/1990",
        "address": "No 18 Allen Str Ikeja"
    }
}
 

Request      

POST api/traders/profile/update

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

address   string  optional  

The trader's address. Example: No 18 Allen Str Ikeja

gender   string  optional  

The trader's gender. Example: Male

email   string  optional  

The trader's email. Example: [email protected]

Get all bank details for the authenticated trader

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/traders/bank-details" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/traders/bank-details"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Bank details retrieved successfully",
    "data": [
        {
            "id": 1,
            "bank_name": "GTB",
            "account_type": "savings",
            "account_number": "1234567890",
            "bank_code": "058"
        }
    ]
}
 

Example response (404):


{
    "message": "No bank details found",
    "details": []
}
 

Request      

GET api/traders/bank-details

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Get a specific bank detail by ID

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/traders/bank-details/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/traders/bank-details/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Bank detail retrieved successfully",
    "data": {
        "id": 1,
        "bank_name": "GTB",
        "account_type": "savings",
        "account_number": "1234567890",
        "bank_code": "058"
    }
}
 

Example response (404):


{
    "message": "Bank detail not found",
    "details": []
}
 

Request      

GET api/traders/bank-details/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the bank detail. Example: 1

Store a new bank detail for the trader

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/bank-details" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"bank_name\": \"GTB\",
    \"account_type\": \"savings\",
    \"account_number\": \"1234567890\",
    \"bank_code\": \"058\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/bank-details"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "bank_name": "GTB",
    "account_type": "savings",
    "account_number": "1234567890",
    "bank_code": "058"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (201):


{
    "message": "Bank detail created successfully",
    "data": {
        "id": 1,
        "bank_name": "GTB",
        "account_type": "savings",
        "account_number": "1234567890",
        "bank_code": "058",
        "recipient_code": "RCP_1a2b3c4d5e6f"
    }
}
 

Example response (400):


{
    "message": "Validation error",
    "details": {
        "bank_name": [
            "The bank name field is required."
        ]
    }
}
 

Request      

POST api/traders/bank-details

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

bank_name   string   

The name of the bank. Example: GTB

account_type   string   

The type of account (savings/current). Example: savings

account_number   string   

The account number. Example: 1234567890

bank_code   string   

The bank code. Example: 058

Update a bank detail

Example request:
curl --request PUT \
    "https://api.sabisave.com/api/traders/bank-details/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"bank_name\": \"GTB\",
    \"account_type\": \"savings\",
    \"account_number\": \"1234567890\",
    \"bank_code\": \"058\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/bank-details/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "bank_name": "GTB",
    "account_type": "savings",
    "account_number": "1234567890",
    "bank_code": "058"
};

fetch(url, {
    method: "PUT",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Bank detail updated successfully",
    "data": {
        "id": 1,
        "bank_name": "GTB",
        "account_type": "savings",
        "account_number": "1234567890",
        "bank_code": "058",
        "recipient_code": "RCP_1a2b3c4d5e6f"
    }
}
 

Example response (404):


{
    "message": "Bank detail not found",
    "details": []
}
 

Request      

PUT api/traders/bank-details/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the bank detail. Example: 1

Body Parameters

bank_name   string  optional  

The name of the bank. Example: GTB

account_type   string  optional  

The type of account (savings/current). Example: savings

account_number   string  optional  

The account number. Example: 1234567890

bank_code   string  optional  

The bank code. Example: 058

Delete a bank detail

Example request:
curl --request DELETE \
    "https://api.sabisave.com/api/traders/bank-details/1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/traders/bank-details/1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "DELETE",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Bank detail deleted successfully"
}
 

Example response (404):


{
    "message": "Bank detail not found",
    "details": []
}
 

Request      

DELETE api/traders/bank-details/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   integer   

The ID of the bank detail. Example: 1

Process a withdrawal request

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/withdraw" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"amount\": \"1000\",
    \"type\": \"cash\",
    \"pin\": \"1234\",
    \"bank_id\": 1
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/withdraw"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "amount": "1000",
    "type": "cash",
    "pin": "1234",
    "bank_id": 1
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Withdrawal request processed successfully",
    "data": {
        "success": true
    }
}
 

Example response (400):


{
    "message": "Insufficient funds",
    "details": []
}
 

Example response (401):


{
    "message": "Invalid PIN",
    "details": []
}
 

Example response (404):


{
    "message": "Trader not found",
    "details": []
}
 

Request      

POST api/traders/withdraw

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

amount   numeric   

The amount to withdraw. Example: 1000

type   string   

The type of withdrawal (cash/transfer). Example: cash

pin   string   

The trader's transaction PIN. Example: 1234

bank_id   integer   

The trader's bank details id. Example: 1

Get Trader's Current Savings Plan

requires authentication

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/traders/savings-plan" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/traders/savings-plan"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Savings plan retrieved successfully",
    "data": {
        "id": 1,
        "frequency": "daily",
        "amount": "1000",
        "trader_id": 1,
        "created_at": "2024-08-15T06:30:00.000000Z",
        "updated_at": "2024-08-15T06:30:00.000000Z"
    }
}
 

Example response (404):


{
    "message": "No savings plan found"
}
 

Request      

GET api/traders/savings-plan

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Create Savings Plan (for traders who don't have one)

requires authentication

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/savings-plan" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"frequency\": \"daily\",
    \"amount\": \"1000\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/savings-plan"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "frequency": "daily",
    "amount": "1000"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (201):


{
    "message": "Savings plan created successfully",
    "data": {
        "id": 1,
        "frequency": "daily",
        "amount": "1000",
        "trader_id": 1,
        "created_at": "2024-08-15T06:30:00.000000Z",
        "updated_at": "2024-08-15T06:30:00.000000Z"
    }
}
 

Example response (409):


{
    "message": "Savings plan already exists"
}
 

Request      

POST api/traders/savings-plan

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

frequency   string   

The frequency of savings (daily, weekly, monthly). Example: daily

amount   numeric   

The amount to save (minimum 100). Example: 1000

Update Trader's Savings Plan

requires authentication

Example request:
curl --request PUT \
    "https://api.sabisave.com/api/traders/savings-plan" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"frequency\": \"weekly\",
    \"amount\": \"2000\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/savings-plan"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "frequency": "weekly",
    "amount": "2000"
};

fetch(url, {
    method: "PUT",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "message": "Savings plan updated successfully",
    "data": {
        "id": 1,
        "frequency": "weekly",
        "amount": "2000",
        "trader_id": 1,
        "created_at": "2024-08-15T06:30:00.000000Z",
        "updated_at": "2024-08-15T06:45:00.000000Z"
    }
}
 

Example response (404):


{
    "message": "No savings plan found"
}
 

Example response (422):


{
    "message": "Validation failed",
    "details": {
        "frequency": [
            "The selected frequency is invalid."
        ],
        "amount": [
            "The amount must be at least 100."
        ]
    }
}
 

Request      

PUT api/traders/savings-plan

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

frequency   string   

The frequency of savings (daily, weekly, monthly). Example: weekly

amount   numeric   

The amount to save (minimum 100). Example: 2000

Delete Trader's Savings Plan

requires authentication

Example request:
curl --request DELETE \
    "https://api.sabisave.com/api/traders/savings-plan" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/traders/savings-plan"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "DELETE",
    headers,
}).then(response => response.json());

Example response (200):


{
    "message": "Savings plan deleted successfully"
}
 

Example response (404):


{
    "message": "No savings plan found"
}
 

Request      

DELETE api/traders/savings-plan

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Transactions

List all transactions

requires authentication

Retrieves a paginated list of all transactions (both trader and agent) with optional filtering.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/transactions?user_type=trader&user_id=1&start_date=2023-01-01&end_date=2023-12-31&transaction_type=deposit&collection_type=cash&status=1&page=1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/transactions"
);

const params = {
    "user_type": "trader",
    "user_id": "1",
    "start_date": "2023-01-01",
    "end_date": "2023-12-31",
    "transaction_type": "deposit",
    "collection_type": "cash",
    "status": "1",
    "page": "1",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Transactions retrieved successfully",
    "data": {
        "transactions": {
            "data": [
                {
                    "id": 1,
                    "amount": 10000,
                    "type": "deposit",
                    "ref_id": "TRX123456",
                    "trader_id": 1,
                    "agent_id": 2,
                    "status_id": 1,
                    "status": {
                        "id": 1,
                        "name": "completed"
                    },
                    "recipient": null,
                    "reason": null,
                    "ref_type": "deposit",
                    "created_at": "2023-01-01 12:00:00",
                    "updated_at": "2023-01-01 12:00:00",
                    "trader": {
                        "id": 1,
                        "name": "John Doe"
                    },
                    "agent": {
                        "id": 2,
                        "name": "Jane Smith"
                    }
                }
            ],
            "links": {
                "first": "http://example.com/api/admin/transactions?page=1",
                "last": "http://example.com/api/admin/transactions?page=5",
                "prev": null,
                "next": "http://example.com/api/admin/transactions?page=2"
            },
            "meta": {
                "current_page": 1,
                "from": 1,
                "last_page": 5,
                "path": "http://example.com/api/admin/transactions",
                "per_page": 10,
                "to": 10,
                "total": 50
            }
        }
    }
}
 

Example response (422):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "The user type must be one of the following types: trader, agent",
    "data": null
}
 

Example response (500):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Internal server error",
    "data": null
}
 

Request      

GET api/admin/transactions

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Query Parameters

user_type   string  optional  

Filter by user type (trader, agent, or all). Example: trader

user_id   integer  optional  

Filter by specific user ID. Example: 1

start_date   string  optional  

date Start date for filtering transactions (YYYY-MM-DD). Example: 2023-01-01

end_date   string  optional  

date End date for filtering transactions (YYYY-MM-DD). Example: 2023-12-31

transaction_type   string  optional  

Filter by transaction type (deposit/withdrawal). Example: deposit

collection_type   string  optional  

Filter by collection type. Example: cash

status   integer  optional  

Filter by status ID. Example: 1

page   integer  optional  

Page number for pagination. Example: 1

Get transaction statistics

requires authentication

Retrieves summary statistics for all transactions, including monthly trends and totals.

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/admin/transactions/statistics" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/admin/transactions/statistics"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": true,
    "message": "Transaction statistics retrieved successfully",
    "data": {
        "summary": {
            "total_deposits": 500000,
            "total_withdrawals": 200000,
            "net_balance": 300000,
            "trader_count": 50,
            "agent_count": 20,
            "transaction_count": 500
        },
        "monthly_trends": {
            "labels": [
                "Jan",
                "Feb",
                "Mar",
                "Apr",
                "May",
                "Jun",
                "Jul",
                "Aug",
                "Sep",
                "Oct",
                "Nov",
                "Dec"
            ],
            "datasets": [
                {
                    "label": "Trader Deposits",
                    "data": [
                        10000,
                        15000,
                        20000,
                        25000,
                        30000,
                        35000,
                        40000,
                        45000,
                        50000,
                        55000,
                        60000,
                        65000
                    ]
                },
                {
                    "label": "Trader Withdrawals",
                    "data": [
                        5000,
                        7500,
                        10000,
                        12500,
                        15000,
                        17500,
                        20000,
                        22500,
                        25000,
                        27500,
                        30000,
                        32500
                    ]
                },
                {
                    "label": "Agent Deposits",
                    "data": [
                        8000,
                        12000,
                        16000,
                        20000,
                        24000,
                        28000,
                        32000,
                        36000,
                        40000,
                        44000,
                        48000,
                        52000
                    ]
                },
                {
                    "label": "Agent Withdrawals",
                    "data": [
                        4000,
                        6000,
                        8000,
                        10000,
                        12000,
                        14000,
                        16000,
                        18000,
                        20000,
                        22000,
                        24000,
                        26000
                    ]
                }
            ]
        },
        "status_breakdown": {
            "completed": 450,
            "pending": 30,
            "failed": 20
        }
    }
}
 

Example response (500):


{
    "timestamp": "2023-01-01T12:00:00.000000Z",
    "status": false,
    "message": "Internal server error",
    "data": null
}
 

Request      

GET api/admin/transactions/statistics

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Updates

Trader Registration Updated simplified trader registration APIs

Step 1: Create Trader Account (Simplified Registration)

This is the first step of the new simplified 4-step registration process. Creates a trader account with basic information and sends OTP for verification.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/register" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"first_name\": \"John\",
    \"last_name\": \"Smith\",
    \"phone\": \"+2348013221673\",
    \"dob\": \"2000-01-15\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/register"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "first_name": "John",
    "last_name": "Smith",
    "phone": "+2348013221673",
    "dob": "2000-01-15"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "status": 1,
    "message": "Registration successful. OTP sent to your phone number for verification",
    "data": {
        "id": 4,
        "first_name": "John",
        "last_name": "Smith",
        "phone": "+2348013221673",
        "dob": "2000-01-15",
        "account_number": "8013221673",
        "created_at": "2024-01-01T12:00:00.000000Z"
    }
}
 

Example response (422):


{
    "status": 0,
    "message": "Validation failed",
    "errors": {
        "first_name": [
            "The first name field is required."
        ],
        "phone": [
            "The phone number format is invalid.",
            "The phone has already been taken."
        ],
        "dob": [
            "The date of birth must be before today."
        ]
    }
}
 

Example response (500):


{
    "status": 0,
    "message": "Unable to create user",
    "code": 500
}
 

Request      

POST api/traders/register

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

none   string  optional  

Example: saepe

Body Parameters

first_name   string   

The first name of the user. Example: John

last_name   string   

The last name of the user. Example: Smith

phone   string   

The phone number (Nigerian format). Example: +2348013221673

dob   date   

The date of birth (must be in the past). Example: 2000-01-15

Step 2: Verify Phone Number (Simplified Registration)

Verifies the OTP code sent to the trader's phone number. This is the second step in the simplified registration process. After successful verification, the user can proceed to create their PIN.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/verify-phone" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"phone\": \"+2348012345678\",
    \"token\": \"123456\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/verify-phone"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "phone": "+2348012345678",
    "token": "123456"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "status": 1,
    "message": "Verification successful",
    "data": {
        "trader_id": 1,
        "phone": "+2348012345678",
        "verified_at": "2024-01-01T12:05:00.000000Z"
    }
}
 

Example response (400):


{
    "status": 0,
    "message": "Invalid or expired verification code",
    "code": 400
}
 

Example response (404):


{
    "status": 0,
    "message": "Trader not found",
    "code": 404
}
 

Example response (422):


{
    "status": 0,
    "message": "Validation failed",
    "errors": {
        "phone": [
            "The phone field is required.",
            "The selected phone is invalid."
        ],
        "token": [
            "The token field is required.",
            "The token must be numeric."
        ]
    }
}
 

Example response (500):


{
    "status": 0,
    "message": "Verification failed",
    "code": 500
}
 

Request      

POST api/traders/verify-phone

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

none   string  optional  

Example: voluptatem

Body Parameters

phone   string   

The phone number of the trader. Example: +2348012345678

token   string   

The 6-digit verification code. Example: 123456

Step 2a: Resend Phone Verification Code (Simplified Registration)

Resends the OTP verification code to the trader's phone number. Used when the initial OTP expires or is not received.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/resend-verification" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"phone\": \"+2348012345678\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/resend-verification"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "phone": "+2348012345678"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "status": 1,
    "message": "Verification code sent successfully",
    "data": []
}
 

Example response (404):


{
    "status": 0,
    "message": "Trader not found",
    "code": 404
}
 

Example response (422):


{
    "status": 0,
    "message": "Validation failed",
    "errors": {
        "phone": [
            "The phone field is required.",
            "The selected phone is invalid."
        ]
    }
}
 

Example response (500):


{
    "status": 0,
    "message": "Failed to send verification code",
    "code": 500
}
 

Request      

POST api/traders/resend-verification

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

none   string  optional  

Example: ipsam

Body Parameters

phone   string   

The phone number of the trader. Example: +2348012345678

Step 3: Create PIN and Complete Registration (Simplified Registration)

This is the final step of the simplified registration process. Creates the trader's 4-digit PIN and completes account setup. After this step, the account is fully created and ready for use.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/traders/create-pin" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"pin\": \"1234\",
    \"pin_confirmation\": \"1234\",
    \"trader_id\": \"1\"
}"
const url = new URL(
    "https://api.sabisave.com/api/traders/create-pin"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "pin": "1234",
    "pin_confirmation": "1234",
    "trader_id": "1"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "status": 1,
    "message": "Account created successfully",
    "data": {
        "trader": {
            "id": 1,
            "first_name": "John",
            "last_name": "Smith",
            "phone": "+2348012345678",
            "account_number": "8012345678",
            "dob": "2000-01-15",
            "created_at": "2024-01-01T12:00:00.000000Z",
            "phone_number_verified_at": "2024-01-01T12:05:00.000000Z"
        }
    }
}
 

Example response (403):


{
    "status": 0,
    "message": "Phone number not verified",
    "code": 403
}
 

Example response (404):


{
    "status": 0,
    "message": "Trader not found",
    "code": 404
}
 

Example response (422):


{
    "status": 0,
    "message": "Validation failed",
    "errors": {
        "pin": [
            "The pin field is required.",
            "The pin must be exactly 4 digits."
        ],
        "pin_confirmation": [
            "The pin confirmation does not match."
        ]
    }
}
 

Example response (500):


{
    "status": 0,
    "message": "Failed to create PIN",
    "code": 500
}
 

Request      

POST api/traders/create-pin

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

none   string  optional  

Example: exercitationem

Body Parameters

pin   string   

4-digit transaction PIN. Example: 1234

pin_confirmation   string   

PIN confirmation (must match pin). Example: 1234

trader_id   numeric   

The ID of the trader from step 1. Example: 1

Agent Registration Simplified agent registration APIs

Step 1: Agent Account Setup (Simplified Registration)

Creates a new agent account with basic information and sends OTP verification. This is the first step in the simplified 4-step registration process.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/register" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"first_name\": \"John\",
    \"last_name\": \"Doe\",
    \"phone\": \"+2348012345678\",
    \"dob\": \"1990-01-15\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/register"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "first_name": "John",
    "last_name": "Doe",
    "phone": "+2348012345678",
    "dob": "1990-01-15"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (201):


{
    "status": 1,
    "message": "Agent registration successful. Please verify your phone number.",
    "data": {
        "id": 1,
        "first_name": "John",
        "last_name": "Doe",
        "phone": "+2348012345678",
        "dob": "1990-01-15",
        "account_number": "8012345678",
        "phone_verified_at": null,
        "created_at": "2025-01-02T10:30:00.000000Z",
        "updated_at": "2025-01-02T10:30:00.000000Z"
    }
}
 

Example response (422):


{
    "status": 0,
    "message": "Validation failed",
    "errors": {
        "phone": [
            "The phone has already been taken."
        ]
    }
}
 

Request      

POST api/agents/register

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

none   string  optional  

Example: voluptatibus

Body Parameters

first_name   string   

The first name of the agent. Example: John

last_name   string   

The last name of the agent. Example: Doe

phone   string   

The phone number of the agent. Example: +2348012345678

dob   date   

The date of birth of the agent. Example: 1990-01-15

Step 3: Create Agent PIN (Simplified Registration)

Creates a 4-digit PIN for the agent and completes the registration process. This is the final step in the simplified registration flow.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/create-pin" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"phone\": \"+2348012345678\",
    \"pin\": \"1234\",
    \"pin_confirmation\": \"1234\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/create-pin"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "phone": "+2348012345678",
    "pin": "1234",
    "pin_confirmation": "1234"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "status": 1,
    "message": "PIN created successfully. Agent registration completed.",
    "data": {
        "id": 1,
        "first_name": "John",
        "last_name": "Doe",
        "phone": "+2348012345678",
        "dob": "1990-01-15",
        "account_number": "8012345678",
        "phone_verified_at": "2025-01-02T10:35:00.000000Z",
        "created_at": "2025-01-02T10:30:00.000000Z",
        "updated_at": "2025-01-02T10:35:00.000000Z"
    }
}
 

Example response (404):


{
    "status": 0,
    "message": "Agent not found or phone not verified"
}
 

Example response (422):


{
    "status": 0,
    "message": "Validation failed",
    "errors": {
        "pin": [
            "The pin confirmation does not match."
        ]
    }
}
 

Request      

POST api/agents/create-pin

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

none   string  optional  

Example: impedit

Body Parameters

phone   string   

The phone number of the agent. Example: +2348012345678

pin   string   

The 4-digit PIN. Example: 1234

pin_confirmation   string   

The PIN confirmation. Example: 1234

Agent Registration Agent phone verification APIs for the simplified registration flow

Step 2: Phone Number Verification

Verifies the OTP code sent to the agent's phone number during registration. This is the second step in the simplified 4-step registration process.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/verify-phone" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"phone\": \"+2348012345678\",
    \"token\": \"1234\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/verify-phone"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "phone": "+2348012345678",
    "token": "1234"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "status": true,
    "message": "Verification successful",
    "data": []
}
 

Example response (400):


{
    "status": false,
    "message": "Invalid or expired verification code",
    "data": []
}
 

Example response (404):


{
    "status": false,
    "message": "Agent not found",
    "data": []
}
 

Example response (500):


{
    "status": false,
    "message": "Failed to verify token",
    "data": []
}
 

Request      

POST api/agents/verify-phone

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

phone   string   

The phone number of the agent. Example: +2348012345678

token   string   

The 4-digit verification code. Example: 1234

Step 2a: Resend Phone Verification Code

Resends the OTP verification code to the agent's phone number during registration.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/resend-verification" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"phone\": \"+2348012345678\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/resend-verification"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "phone": "+2348012345678"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "status": true,
    "message": "Verification code resent successfully",
    "data": []
}
 

Example response (404):


{
    "status": false,
    "message": "Agent not found",
    "data": []
}
 

Example response (500):


{
    "status": false,
    "message": "Failed to resend verification code",
    "data": []
}
 

Request      

POST api/agents/resend-verification

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

phone   string   

The phone number of the agent. Example: +2348012345678

Step 2: Phone Number Verification

Verifies the OTP code sent to the agent's phone number during registration. This is the second step in the simplified 4-step registration process.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/trader-onboarding/verify-phone" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"phone\": \"+2348012345678\",
    \"token\": \"1234\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/trader-onboarding/verify-phone"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "phone": "+2348012345678",
    "token": "1234"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "status": true,
    "message": "Verification successful",
    "data": []
}
 

Example response (400):


{
    "status": false,
    "message": "Invalid or expired verification code",
    "data": []
}
 

Example response (404):


{
    "status": false,
    "message": "Agent not found",
    "data": []
}
 

Example response (500):


{
    "status": false,
    "message": "Failed to verify token",
    "data": []
}
 

Request      

POST api/agents/trader-onboarding/verify-phone

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

phone   string   

The phone number of the agent. Example: +2348012345678

token   string   

The 4-digit verification code. Example: 1234

Step 2a: Resend Phone Verification Code

Resends the OTP verification code to the agent's phone number during registration.

Example request:
curl --request POST \
    "https://api.sabisave.com/api/agents/trader-onboarding/resend-verification" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"phone\": \"+2348012345678\"
}"
const url = new URL(
    "https://api.sabisave.com/api/agents/trader-onboarding/resend-verification"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "phone": "+2348012345678"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "status": true,
    "message": "Verification code resent successfully",
    "data": []
}
 

Example response (404):


{
    "status": false,
    "message": "Agent not found",
    "data": []
}
 

Example response (500):


{
    "status": false,
    "message": "Failed to resend verification code",
    "data": []
}
 

Request      

POST api/agents/trader-onboarding/resend-verification

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

phone   string   

The phone number of the agent. Example: +2348012345678

Wallet

APIs for wallet management, transfers, and transactions

POST api/wallets

Example request:
curl --request POST \
    "https://api.sabisave.com/api/wallets" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"account_name\": \"xbdgrndusorafznbhxkwnuz\",
    \"phone_number\": \"rerum\",
    \"email\": \"[email protected]\",
    \"bvn\": \"mniqofrppy\",
    \"nin\": \"wueqrso\",
    \"gender\": \"0\",
    \"address\": \"laudantium\",
    \"date_of_birth\": \"18\\/11\\/2025\",
    \"last_name\": \"occaecati\",
    \"other_names\": \"ut\",
    \"place_of_birth\": \"quasi\"
}"
const url = new URL(
    "https://api.sabisave.com/api/wallets"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "account_name": "xbdgrndusorafznbhxkwnuz",
    "phone_number": "rerum",
    "email": "[email protected]",
    "bvn": "mniqofrppy",
    "nin": "wueqrso",
    "gender": "0",
    "address": "laudantium",
    "date_of_birth": "18\/11\/2025",
    "last_name": "occaecati",
    "other_names": "ut",
    "place_of_birth": "quasi"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/wallets

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

account_name   string   

Must not be greater than 100 characters. Example: xbdgrndusorafznbhxkwnuz

phone_number   string   

Example: rerum

email   string   

Must be a valid email address. Example: [email protected]

bvn   string  optional  

Must be at least 11 characters. Must not be greater than 11 characters. Example: mniqofrppy

nin   string   

Must be at least 11 characters. Must not be greater than 11 characters. Example: wueqrso

gender   string  optional  

Example: 0

Must be one of:
  • 0
  • 1
address   string  optional  

Example: laudantium

date_of_birth   string   

Must be a valid date in the format d/m/Y. Example: 18/11/2025

last_name   string  optional  

Example: occaecati

other_names   string   

Example: ut

place_of_birth   string  optional  

Example: quasi

GET api/wallets/{id}

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/wallets/saepe" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/wallets/saepe"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (403):

Show headers
cache-control: no-cache, private
content-type: application/json
vary: Origin
 

{
    "status": false,
    "message": "Unauthorize"
}
 

Request      

GET api/wallets/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the wallet. Example: saepe

POST api/wallets/{id}/withdraw

Example request:
curl --request POST \
    "https://api.sabisave.com/api/wallets/itaque/withdraw" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"bank_detail_id\": \"vel\",
    \"amount\": 47,
    \"narration\": \"hogbamjvaowskng\"
}"
const url = new URL(
    "https://api.sabisave.com/api/wallets/itaque/withdraw"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "bank_detail_id": "vel",
    "amount": 47,
    "narration": "hogbamjvaowskng"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/wallets/{id}/withdraw

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the wallet. Example: itaque

Body Parameters

bank_detail_id   string   

Example: vel

amount   number   

Must be at least 1. Example: 47

narration   string  optional  

Must not be greater than 255 characters. Example: hogbamjvaowskng

POST api/wallets/{id}/transfer

Example request:
curl --request POST \
    "https://api.sabisave.com/api/wallets/laboriosam/transfer" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"destination_wallet_id\": \"culpa\",
    \"amount\": 57,
    \"narration\": \"tyvwzlwklnvjpnaj\"
}"
const url = new URL(
    "https://api.sabisave.com/api/wallets/laboriosam/transfer"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "destination_wallet_id": "culpa",
    "amount": 57,
    "narration": "tyvwzlwklnvjpnaj"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/wallets/{id}/transfer

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the wallet. Example: laboriosam

Body Parameters

destination_wallet_id   string   

Example: culpa

amount   number   

Must be at least 1. Example: 57

narration   string  optional  

Must not be greater than 255 characters. Example: tyvwzlwklnvjpnaj

GET api/wallets/{id}/transactions

Example request:
curl --request GET \
    --get "https://api.sabisave.com/api/wallets/architecto/transactions" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.sabisave.com/api/wallets/architecto/transactions"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (403):

Show headers
cache-control: no-cache, private
content-type: application/json
vary: Origin
 

{
    "status": false,
    "message": "Unauthorize"
}
 

Request      

GET api/wallets/{id}/transactions

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the wallet. Example: architecto

POST api/wallets/{id}/deposit

Example request:
curl --request POST \
    "https://api.sabisave.com/api/wallets/officiis/deposit" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"amount\": 11,
    \"source\": \"sed\",
    \"narration\": \"sunt\"
}"
const url = new URL(
    "https://api.sabisave.com/api/wallets/officiis/deposit"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "amount": 11,
    "source": "sed",
    "narration": "sunt"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/wallets/{id}/deposit

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the wallet. Example: officiis

Body Parameters

amount   number   

Must be at least 1. Example: 11

source   string  optional  

Example: sed

narration   string  optional  

Example: sunt