Skip to content
Demo environment. M-Pesa and DMVIC are simulated; no real money or certificates move. Sandbox details
FlexySure

Premium finance

9 endpoints · base URL https://flexysure.intrepidprojects.co.ke/api/v1

Spread a premium over monthly instalments with Flexysure Premium Finance: quote, apply, sign the agreement with a one-time code, collect the deposit and follow the loan. Offered through brokerages and agencies only: a SACCO or microfinance token gets 403 ipf_not_offered. Credit decisions and paying the underwriter stay with Flexysure Finance staff; there is no API to approve an application or disburse a loan. Instalments are paid to Flexysure Finance's paybill with the loan ref as the account number, or by an M-Pesa prompt: POST /payment/stk/push with the loan ref as account (purpose ipf_repayment). A running loan can be settled early with POST /ipf/loans/{uuid}/early-settlement. Rule failures from the finance actions come back as 422 validation_failed with the reason under errors.ipf (or errors.otp, errors.tenor_months).

MethodPathSummaryScope
GET /api/v1/ipf/offers Get finance offers for a policy Flexysure only finance
POST /api/v1/ipf/applications Apply for premium finance Flexysure only finance
GET /api/v1/ipf/applications/{uuid} Get an application Flexysure only finance
POST /api/v1/ipf/applications/{uuid}/otp Send the agreement signing code Flexysure only finance
POST /api/v1/ipf/applications/{uuid}/sign Sign the agreement Flexysure only finance
GET /api/v1/ipf/loans/{uuid} Get a loan Flexysure only finance
GET /api/v1/ipf/loans/{uuid}/agreement Download the signed agreement Flexysure only finance
POST /api/v1/ipf/loans/{uuid}/deposit Collect the deposit by M-Pesa Flexysure only finance
POST /api/v1/ipf/loans/{uuid}/early-settlement Quote or start early settlement Flexysure only finance
GET /api/v1/ipf/offers Flexysure only

Get finance offers for a policy

One offer per repayment period the lender offers (deposit, financed amount, interest, fees, instalment, APR) and whether this policy can apply now. A policy must be saved with premium finance as its payment mode and be awaiting payment.

Scope
finance
Authentication
Bearer token
Rate limit
60 requests per minute per token (per-client override)
Idempotency
Safe to repeat (read only).

Headers

HeaderMeaning
AuthorizationBearer <access_token> (scope finance)

Parameters

NameInTypeRequiredDescription
policy query string Yes Policy uuid.

Example

Request cURL
curl -X GET 'https://flexysure.intrepidprojects.co.ke/api/v1/ipf/offers' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Accept: application/json'
Response JSON
{
    "data": {
        "policy": {
            "uuid": "5d0c…",
            "policy_no": "POL/2026/000099",
            "payment_mode": "ipf",
            "status": "pending_payment"
        },
        "lender": {
            "code": "FLEXY",
            "name": "Flexysure Premium Finance"
        },
        "eligible": true,
        "reason": null,
        "gross_premium": 50000,
        "gross_premium_minor": 5000000,
        "offers": [
            {
                "tenor_months": 6,
                "deposit": 10000,
                "deposit_minor": 1000000,
                "principal": 40000,
                "principal_minor": 4000000,
                "interest": 6000,
                "interest_minor": 600000,
                "fees": 500,
                "fees_minor": 50000,
                "total_repayable": 46500,
                "total_repayable_minor": 4650000,
                "instalment": 7749,
                "instalment_minor": 774900,
                "last_instalment": 7755,
                "last_instalment_minor": 775500,
                "apr_percent": 47.6
            }
        ]
    }
}

Responses

StatusMeaning
200 Offers and eligibility
403 ipf_not_offered (SACCO or microfinance organisation)
404 Unknown policy

Errors are problem documents; the common codes (401, 403 insufficient_scope, 422, 429) apply to every endpoint.

POST /api/v1/ipf/applications Flexysure only

Apply for premium finance

Submits the application to Flexysure Finance, who decide in their portal. Calling this confirms the client agreed to the terms and to sharing their details with the lender; the time is recorded as consent_at. The application is owned by the API client's actor user (or the user who created the client).

Scope
finance
Authentication
Bearer token
Rate limit
60 requests per minute per token (per-client override)
Idempotency
Required: send an Idempotency-Key; a retry with the same key replays the first response.

Headers

HeaderMeaning
AuthorizationBearer <access_token> (scope finance)
Idempotency-KeyRequired. A unique value (a UUID) per write. Replays within 24 hours return the stored response with Idempotent-Replayed: true; the same key with a different body is rejected (idempotency_key_reused).

Body fields

FieldTypeRequiredDescription
policy string Yes Policy uuid (payment mode ipf, awaiting payment).
tenor_months integer Yes One of the offered repayment periods. Example: 6

Example

Request cURL
curl -X POST 'https://flexysure.intrepidprojects.co.ke/api/v1/ipf/applications' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Accept: application/json' \
  -H 'Idempotency-Key: fcfcc38f-c811-4548-ac9a-0be0ecb27808' \
  -H 'Content-Type: application/json' \
  -d '{
    "policy": "5d0c8a1e-…",
    "tenor_months": 6
}'
Request body (JSON)
Request body JSON
{
    "policy": "5d0c8a1e-…",
    "tenor_months": 6
}
Response JSON
{
    "data": {
        "uuid": "0c8d6a3e-2f4b-4d0a-9f3e-6b7d1c2a9e44",
        "status": "submitted",
        "status_label": "With lender",
        "next_step": "Waiting for Flexysure Finance to decide.",
        "policy": {
            "uuid": "5d0c…",
            "policy_no": "POL/2026/000099",
            "risk_note_no": "RN/2026/000099"
        },
        "client": {
            "client_no": "C000231",
            "name": "Wanjiru Kamau"
        },
        "lender": {
            "code": "FLEXY",
            "name": "Flexysure Premium Finance"
        },
        "tenor_months": 6,
        "gross_premium": 50000,
        "gross_premium_minor": 5000000,
        "deposit": 10000,
        "deposit_minor": 1000000,
        "principal": 40000,
        "principal_minor": 4000000,
        "interest": 6000,
        "interest_minor": 600000,
        "fees": 500,
        "fees_minor": 50000,
        "total_repayable": 46500,
        "total_repayable_minor": 4650000,
        "apr_percent": 47.6,
        "consent_at": "2026-10-14T09:00:00+03:00",
        "decided_at": null,
        "decline_reason": null,
        "loan_uuid": null,
        "loan_ref": null,
        "created_at": "2026-10-14T09:00:00+03:00"
    }
}

Responses

StatusMeaning
201 Application submitted (status: submitted)
403 ipf_not_offered
404 Unknown policy
422 Not eligible, already applied, or a period the lender does not offer (errors.ipf / errors.tenor_months)

Errors are problem documents; the common codes (401, 403 insufficient_scope, 422, 429) apply to every endpoint.

GET /api/v1/ipf/applications/{uuid} Flexysure only

Get an application

Poll this (or subscribe to ipf.application.decided) to learn the lender's decision. Once signed, loan_uuid points at the loan.

Scope
finance
Authentication
Bearer token
Rate limit
60 requests per minute per token (per-client override)
Idempotency
Safe to repeat (read only).

Headers

HeaderMeaning
AuthorizationBearer <access_token> (scope finance)

Parameters

NameInTypeRequiredDescription
uuid path string Yes Application uuid.

Example

Request cURL
curl -X GET 'https://flexysure.intrepidprojects.co.ke/api/v1/ipf/applications/{uuid}' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Accept: application/json'
Response JSON
{
    "data": {
        "uuid": "0c8d6a3e-2f4b-4d0a-9f3e-6b7d1c2a9e44",
        "status": "approved",
        "status_label": "Approved",
        "next_step": "Send the signing code (POST …/otp), then sign with it (POST …/sign).",
        "policy": {
            "uuid": "5d0c…",
            "policy_no": "POL/2026/000099",
            "risk_note_no": "RN/2026/000099"
        },
        "client": {
            "client_no": "C000231",
            "name": "Wanjiru Kamau"
        },
        "lender": {
            "code": "FLEXY",
            "name": "Flexysure Premium Finance"
        },
        "tenor_months": 6,
        "gross_premium": 50000,
        "gross_premium_minor": 5000000,
        "deposit": 10000,
        "deposit_minor": 1000000,
        "principal": 40000,
        "principal_minor": 4000000,
        "interest": 6000,
        "interest_minor": 600000,
        "fees": 500,
        "fees_minor": 50000,
        "total_repayable": 46500,
        "total_repayable_minor": 4650000,
        "apr_percent": 47.6,
        "consent_at": "2026-10-14T09:00:00+03:00",
        "decided_at": "2026-10-14T09:30:00+03:00",
        "decline_reason": null,
        "loan_uuid": null,
        "loan_ref": null,
        "created_at": "2026-10-14T09:00:00+03:00"
    }
}

Responses

StatusMeaning
200 Application
403 ipf_not_offered
404 Unknown application

Errors are problem documents; the common codes (401, 403 insufficient_scope, 422, 429) apply to every endpoint.

POST /api/v1/ipf/applications/{uuid}/otp Flexysure only

Send the agreement signing code

Texts a 6-digit code to the client's phone for signing the approved agreement (charged to the SMS balance). sent is true only when the SMS was queued or sent; otherwise sent: false with reason. Each call replaces the previous code; it expires after expires_in seconds and allows 5 tries. Only a hash is stored. In the demo the code also comes back as demo_otp.

Scope
finance
Authentication
Bearer token
Rate limit
60 requests per minute per token (per-client override)
Idempotency
Required: send an Idempotency-Key; a retry with the same key replays the first response.

Headers

HeaderMeaning
AuthorizationBearer <access_token> (scope finance)
Idempotency-KeyRequired. A unique value (a UUID) per write. Replays within 24 hours return the stored response with Idempotent-Replayed: true; the same key with a different body is rejected (idempotency_key_reused).

Parameters

NameInTypeRequiredDescription
uuid path string Yes Application uuid.

Example

Request cURL
curl -X POST 'https://flexysure.intrepidprojects.co.ke/api/v1/ipf/applications/{uuid}/otp' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Accept: application/json' \
  -H 'Idempotency-Key: a99efd5b-e319-4ddc-a801-8b27f5f91f56'
Response JSON
{
    "sent": true,
    "message_status": "sent",
    "phone": "0712 345 678",
    "expires_in": 600,
    "demo_otp": "483920",
    "demo_note": "Demo mode: the code is returned here instead of being sent by SMS."
}

Responses

StatusMeaning
200 {sent: true}, or {sent: false, reason} when the SMS could not go
403 ipf_not_offered
404 Unknown application
422 Not approved yet (errors.ipf)

Errors are problem documents; the common codes (401, 403 insufficient_scope, 422, 429) apply to every endpoint.

POST /api/v1/ipf/applications/{uuid}/sign Flexysure only

Sign the agreement

Checks the code and books the loan in pending_deposit. The signature evidence is the sha256 of the agreement text, the caller's IP and the time. Next: collect the deposit with POST /ipf/loans/{uuid}/deposit.

Scope
finance
Authentication
Bearer token
Rate limit
60 requests per minute per token (per-client override)
Idempotency
Required: send an Idempotency-Key; a retry with the same key replays the first response.

Headers

HeaderMeaning
AuthorizationBearer <access_token> (scope finance)
Idempotency-KeyRequired. A unique value (a UUID) per write. Replays within 24 hours return the stored response with Idempotent-Replayed: true; the same key with a different body is rejected (idempotency_key_reused).

Parameters

NameInTypeRequiredDescription
uuid path string Yes Application uuid.

Body fields

FieldTypeRequiredDescription
otp string Yes The 6-digit code the client received. Example: 483920

Example

Request cURL
curl -X POST 'https://flexysure.intrepidprojects.co.ke/api/v1/ipf/applications/{uuid}/sign' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Accept: application/json' \
  -H 'Idempotency-Key: 696881b3-b788-4875-af9f-82185d8829da' \
  -H 'Content-Type: application/json' \
  -d '{
    "otp": "483920"
}'
Request body (JSON)
Request body JSON
{
    "otp": "483920"
}
Response JSON
{
    "data": {
        "uuid": "1f7e2b9c-8a3d-4e6f-b1c2-3d4e5f6a7b8c",
        "loan_ref": "IPF-000017",
        "status": "pending_deposit",
        "status_label": "Awaiting deposit",
        "application_uuid": "0c8d6a3e-…",
        "policy": {
            "uuid": "5d0c…",
            "policy_no": "POL/2026/000099",
            "status": "active"
        },
        "client": {
            "client_no": "C000231",
            "name": "Wanjiru Kamau"
        },
        "lender": {
            "code": "FLEXY",
            "name": "Flexysure Premium Finance",
            "paybill": "700100"
        },
        "repay_to": {
            "paybill": "700100",
            "account": "IPF-000017"
        },
        "tenor_months": 6,
        "apr_percent": 47.6,
        "total_repayable": 46500,
        "total_repayable_minor": 4650000,
        "repaid": 0,
        "repaid_minor": 0,
        "outstanding": 38751,
        "outstanding_minor": 3875100,
        "principal_outstanding": 33334,
        "principal_outstanding_minor": 3333400,
        "repaid_split": {
            "fees": 83,
            "fees_minor": 8300,
            "interest": 1000,
            "interest_minor": 100000,
            "principal": 6666,
            "principal_minor": 666600
        },
        "arrears": 0,
        "arrears_minor": 0,
        "arrears_days": 0,
        "next_due": null,
        "schedule": [],
        "links": {
            "agreement": "https://app.flexysure.com/api/v1/ipf/loans/1f7e…/agreement"
        }
    }
}

Responses

StatusMeaning
201 Loan created
403 ipf_not_offered
404 Unknown application
422 Wrong or expired code, tries left in the message (errors.otp)

Errors are problem documents; the common codes (401, 403 insufficient_scope, 422, 429) apply to every endpoint.

GET /api/v1/ipf/loans/{uuid} Flexysure only

Get a loan

Terms, repayment schedule, what has been repaid (split fees, then interest, then principal inside each instalment), what is outstanding, arrears and how many days the oldest missed instalment is late. The schedule appears once Flexysure Finance has paid the underwriter.

Scope
finance
Authentication
Bearer token
Rate limit
60 requests per minute per token (per-client override)
Idempotency
Safe to repeat (read only).

Headers

HeaderMeaning
AuthorizationBearer <access_token> (scope finance)

Parameters

NameInTypeRequiredDescription
uuid path string Yes Loan uuid.

Example

Request cURL
curl -X GET 'https://flexysure.intrepidprojects.co.ke/api/v1/ipf/loans/{uuid}' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Accept: application/json'
Response JSON
{
    "data": {
        "uuid": "1f7e2b9c-8a3d-4e6f-b1c2-3d4e5f6a7b8c",
        "loan_ref": "IPF-000017",
        "status": "active",
        "status_label": "Active",
        "application_uuid": "0c8d6a3e-…",
        "policy": {
            "uuid": "5d0c…",
            "policy_no": "POL/2026/000099",
            "status": "active"
        },
        "client": {
            "client_no": "C000231",
            "name": "Wanjiru Kamau"
        },
        "lender": {
            "code": "FLEXY",
            "name": "Flexysure Premium Finance",
            "paybill": "700100"
        },
        "repay_to": {
            "paybill": "700100",
            "account": "IPF-000017"
        },
        "tenor_months": 6,
        "apr_percent": 47.6,
        "total_repayable": 46500,
        "total_repayable_minor": 4650000,
        "repaid": 7749,
        "repaid_minor": 774900,
        "outstanding": 38751,
        "outstanding_minor": 3875100,
        "principal_outstanding": 33334,
        "principal_outstanding_minor": 3333400,
        "repaid_split": {
            "fees": 83,
            "fees_minor": 8300,
            "interest": 1000,
            "interest_minor": 100000,
            "principal": 6666,
            "principal_minor": 666600
        },
        "arrears": 0,
        "arrears_minor": 0,
        "arrears_days": 0,
        "next_due": {
            "seq": 2,
            "due_on": "2026-12-14",
            "amount": 7749,
            "amount_minor": 774900
        },
        "schedule": [
            {
                "seq": 1,
                "due_on": "2026-11-14",
                "principal": 6666,
                "principal_minor": 666600,
                "interest": 1000,
                "interest_minor": 100000,
                "fees": 83,
                "fees_minor": 8300,
                "amount_due": 7749,
                "amount_due_minor": 774900,
                "amount_paid": 7749,
                "amount_paid_minor": 774900,
                "status": "paid"
            }
        ],
        "links": {
            "agreement": "https://app.flexysure.com/api/v1/ipf/loans/1f7e…/agreement"
        }
    }
}

Responses

StatusMeaning
200 Loan
403 ipf_not_offered
404 Unknown loan

Errors are problem documents; the common codes (401, 403 insufficient_scope, 422, 429) apply to every endpoint.

GET /api/v1/ipf/loans/{uuid}/agreement Flexysure only

Download the signed agreement

The agreement the client signed as a one-page PDF (application/pdf), with the e-signature record: time, document fingerprint and IP.

Scope
finance
Authentication
Bearer token
Rate limit
60 requests per minute per token (per-client override)
Idempotency
Safe to repeat (read only).

Headers

HeaderMeaning
AuthorizationBearer <access_token> (scope finance)

Parameters

NameInTypeRequiredDescription
uuid path string Yes Loan uuid.

Example

Request cURL
curl -X GET 'https://flexysure.intrepidprojects.co.ke/api/v1/ipf/loans/{uuid}/agreement' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Accept: application/json'
Response PDF
%PDF-1.4 … (binary)

Responses

StatusMeaning
200 PDF file
403 ipf_not_offered
404 Unknown loan

Errors are problem documents; the common codes (401, 403 insufficient_scope, 422, 429) apply to every endpoint.

POST /api/v1/ipf/loans/{uuid}/deposit Flexysure only

Collect the deposit by M-Pesa

Sends an STK push for the deposit (purpose ipf_deposit). When the customer pays, the receipt is allocated to the policy's debit note and the loan moves to pending_disbursement; cover starts after Flexysure Finance pays the underwriter. Poll with GET /payment/stk/{uuid}.

Scope
finance
Authentication
Bearer token
Rate limit
60 requests per minute per token (per-client override)
Idempotency
Required: send an Idempotency-Key; a retry with the same key replays the first response.

Headers

HeaderMeaning
AuthorizationBearer <access_token> (scope finance)
Idempotency-KeyRequired. A unique value (a UUID) per write. Replays within 24 hours return the stored response with Idempotent-Replayed: true; the same key with a different body is rejected (idempotency_key_reused).

Parameters

NameInTypeRequiredDescription
uuid path string Yes Loan uuid.

Body fields

FieldTypeRequiredDescription
phone string Yes 07XXXXXXXX or 2547XXXXXXXX. Example: 0712345678

Example

Request cURL
curl -X POST 'https://flexysure.intrepidprojects.co.ke/api/v1/ipf/loans/{uuid}/deposit' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Accept: application/json' \
  -H 'Idempotency-Key: d6c5b4f9-03d1-4040-ac20-fa413a437bcc' \
  -H 'Content-Type: application/json' \
  -d '{
    "phone": "0712345678"
}'
Request body (JSON)
Request body JSON
{
    "phone": "0712345678"
}
Response JSON
{
    "merchant_request_id": "29115-34620561-1",
    "checkout_request_id": "ws_CO_14102026101500123",
    "stk_request_uuid": "9b2f…",
    "status": "pending",
    "purpose": "ipf_deposit",
    "account": "DN-000099",
    "amount": 10000,
    "amount_minor": 1000000,
    "ipf_loan_ref": "IPF-000017"
}

Responses

StatusMeaning
200 Prompt sent (same shape as POST /payment/stk/push)
403 ipf_not_offered
404 Unknown loan
422 deposit_not_due or payment_refused. No money moved.

Errors are problem documents; the common codes (401, 403 insufficient_scope, 422, 429) apply to every endpoint.

POST /api/v1/ipf/loans/{uuid}/early-settlement Flexysure only

Quote or start early settlement

With ?quote=1: the payoff figure for today and nothing else. Without it: the same quote plus an STK push for the payoff amount (phone required). Payoff rule: unpaid principal on every instalment, plus unpaid interest and fees on instalments already due (due date on or before today), plus interest on the current instalment accrued pro rata by days from the previous due date (or one month before the first) to today. Interest and fees on later instalments are waived. Rounded up to the shilling, never more than the contractual outstanding balance, valid today only. Use a new Idempotency-Key for each quote. When the customer pays the prompt (purpose ipf_settlement), the payoff is recomputed for the payment date: paying at least that much closes the loan (status closed), the remaining interest and fees are waived (schedule lines waived), anything above the payoff is kept as a borrower credit, and the loan timeline shows "Settled early". Paying less than the payoff counts as an ordinary instalment and the loan stays open. Poll GET /payment/stk/{uuid} and GET /ipf/loans/{uuid}.

Scope
finance
Authentication
Bearer token
Rate limit
60 requests per minute per token (per-client override)
Idempotency
Required: send an Idempotency-Key; a retry with the same key replays the first response.

Headers

HeaderMeaning
AuthorizationBearer <access_token> (scope finance)
Idempotency-KeyRequired. A unique value (a UUID) per write. Replays within 24 hours return the stored response with Idempotent-Replayed: true; the same key with a different body is rejected (idempotency_key_reused).

Parameters

NameInTypeRequiredDescription
uuid path string Yes Loan uuid.
quote query boolean No 1 to get the payoff figure without sending a prompt.

Body fields

FieldTypeRequiredDescription
phone string No Required unless quote=1. 07XXXXXXXX or 2547XXXXXXXX. Example: 0712345678

Example

Request cURL
curl -X POST 'https://flexysure.intrepidprojects.co.ke/api/v1/ipf/loans/{uuid}/early-settlement' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Accept: application/json' \
  -H 'Idempotency-Key: 25c7ad45-96cb-4f6a-af9d-f8b88cc0208f'
Response JSON
{
    "data": {
        "loan_ref": "IPF-000017",
        "as_of": "2026-12-01",
        "payoff": 34200,
        "payoff_minor": 3420000,
        "principal": 33334,
        "principal_minor": 3333400,
        "interest_accrued": 866,
        "interest_accrued_minor": 86600,
        "fees_due": 0,
        "fees_due_minor": 0,
        "outstanding": 38750,
        "outstanding_minor": 3875000,
        "waived": 4550,
        "waived_minor": 455000,
        "rule": "Unpaid principal + interest and fees on instalments already due + interest accrued pro rata on the current instalment to today; later interest and fees are waived. Valid today only."
    }
}

Responses

StatusMeaning
200 Quote (data), and stk when a prompt was sent
403 ipf_not_offered
404 Unknown loan
422 not_settleable (loan not running), validation_failed (phone missing without quote=1) or payment_refused. No money moved.

Errors are problem documents; the common codes (401, 403 insufficient_scope, 422, 429) apply to every endpoint.