Developers

Partner API Product guide

Insurance

Hollard motor, home and travel policies — quote a premium, collect payment, and FEX issues the policy.

Base URL http://fex.mojo-pay.com/v1
Open API tester

Overview

Everything you need to sell insurance through the FEX Partner API. All paths are relative to the /v1 base URL above. Shared concepts (sandbox vs live, rate limits) are on the Partner API overview.

Integration flow

  1. Get a Bearer token with POST /oauth/token.
  2. List policies with GET /catalog/products?category=insurance_general and read each input_schema (fields differ a lot between motor, home and travel).
  3. Create a quote with the policy details — the quote amount is the premium.
  4. Create an order from the quote and send the customer to payment.url.
  5. After payment FEX issues the policy with Hollard; wait for order.completed or order.failed.

Products

Product Name Provider Required fields Lookup
PRD_HI_HOME
hi-home-policy
Hollard Home Policy Hollard Insurance begin_date end_date home_address —
PRD_HI_MOTOR
hi-motor-policy
Hollard Motor Policy Hollard Insurance sum_insured cover_type cover_type_period risk_category full_name phone email make model year_of_manufacture vehicle_registration inception_date expiry_date body_type_code —
PRD_HI_TRAVEL
hi-travel-policy
Hollard Travel Policy Hollard Insurance plan days age first_name last_name policy_holder_address occupation cover_type passport_id passport_expiry_date destination_country departure_date return_date emergency_contact_number emergency_contact_name emergency_contact_relation —

Orientation only — your credentials see a partner-scoped subset. Always call GET /catalog/products and read each input_schema rather than hardcoding this table.

Authentication

Create a client_id / client_secret under Partner Portal → API credentials, then exchange them for a Bearer token (about 20 minutes). Send Authorization: Bearer <token> on every other call.

Global headers

Header Required Description
Authorization Yes* Bearer <token> (*except token endpoint)
Content-Type POST application/json
Accept Recommended application/json
X-FEX-Country No ISO country (e.g. GH). Defaults to partner profile.
Idempotency-Key Recommended On POST /orders — replay-safe create.
POST /oauth/token No auth

Issue a short-lived Bearer access token.

Send Authorization: Bearer <access_token> on all other routes.

Body parameters

client_id required
string
From Partner Portal → API credentials.
client_secret required
string
Shown once when you generate or rotate credentials in the Partner Portal.
grant_type optional
string
Optional. Must be client_credentials when sent.
POST http://fex.mojo-pay.com/v1/oauth/token
Request
{
  "grant_type": "client_credentials",
  "client_id": "fex_…",
  "client_secret": "…"
}
Response 200
{
  "access_token": "…",
  "token_type": "Bearer",
  "expires_in": 1200
}

Policies

Insurance products are under the insurance_general category. Each policy type has a very different input_schema, including enums for cover types and risk categories.

Policy notes

  • Motor (hi-motor-policy): premium is priced from GH Tariffs. year_of_manufacture must match the registration plate suffix (e.g. GT 7743 18 → 2018). Short-period cover also needs days. The policy activates once Hollard issues the NIC MID sticker.
  • Home (hi-home-policy): send home_estimated_value, home_content_listing (list of {item_name, price_ghs}), or both.
  • Travel (hi-travel-policy): trip length days is 1–92, plus passport and emergency-contact details.
GET /catalog/products Bearer

List insurance products available to your partner.

Query parameters

country optional
string
ISO country code.
category optional
string
Category code from list categories.
GET http://fex.mojo-pay.com/v1/catalog/products
Request
GET /v1/catalog/products?category=insurance_general
Response 200
{
  "object": "list",
  "data": [
    {
      "id": "PRD_HB_ECG",
      "object": "product",
      "code": "hb-ecg-bill",
      "name": "ECG Prepaid & Postpaid",
      "category": "bills",
      "country": "GH",
      "currency": "GHS",
      "status": "sandbox",
      "input_schema": {
        "type": "object",
        "required": ["phone", "meter_number", "amount"],
        "properties": {
          "phone": { "type": "string" },
          "meter_number": { "type": "string" },
          "amount": { "type": "number" }
        }
      },
      "min_amount": "1.00",
      "max_amount": null,
      "provider": { "id": "PRV_…", "code": "…", "name": "…" },
      "lookup_url": "https://…/v1/catalog/products/PRD_HB_ECG/lookup"
    }
  ]
}
GET /catalog/products/{id} Bearer

Retrieve a single product by public id (PRD_…).

Path parameters

id required
string
Product public id.
GET http://fex.mojo-pay.com/v1/catalog/products/{id}
Request
GET /catalog/products/{id}
Authorization: Bearer <token>
Response 200
{
  "id": "PRD_HB_ECG",
  "object": "product",
  "code": "hb-ecg-bill",
  "name": "ECG Prepaid & Postpaid",
  "category": "bills",
  "input_schema": {
    "type": "object",
    "required": ["phone", "meter_number", "amount"],
    "properties": {
      "phone": { "type": "string", "title": "Phone linked to the meter" },
      "meter_number": { "type": "string", "title": "Meter / account number" },
      "amount": { "type": "number", "title": "Amount (GHS)" }
    }
  },
  "provider": { "id": "PRV_…", "code": "…", "name": "…" },
  "lookup_url": "https://…/v1/catalog/products/PRD_HB_ECG/lookup"
}

Quotes

A quote locks the price for the fields you send. Every field must satisfy the product input_schema.

POST /quotes Bearer

Price a product for the submitted fields. Quotes expire — create the order before expires_at.

The quote amount is the premium. Show it to the customer before creating the order.

Body parameters

product_id required
string
Product public id from the catalog.
customer_id optional
string
Optional FEX customer id — provider-specific fields are merged from linked profiles. For SecondsTax, api_user defaults to the customer’s email or phone (same identity used on provider-funds / provider-portfolios).
fields required
object
Must satisfy the product input_schema. Explicit fields override merged customer/profile values (e.g. fields.api_user).
POST http://fex.mojo-pay.com/v1/quotes
Request (home policy)
{
  "product_id": "PRD_HI_HOME",
  "fields": {
    "home_address": "12 Independence Ave, Accra",
    "home_estimated_value": 250000,
    "begin_date": "2026-10-01",
    "end_date": "2027-09-30"
  }
}
Response 201
{
  "id": "QTE_…",
  "object": "quote",
  "product_id": "PRD_HI_HOME",
  "currency": "GHS",
  "amount": "…",
  "amount_payable": "…",
  "expires_at": "2026-08-30T15:00:00+00:00"
}
GET /quotes/{id} Bearer

Retrieve a quote owned by the authenticated partner.

Path parameters

id required
string
Quote public id.
GET http://fex.mojo-pay.com/v1/quotes/{id}
Request
GET /quotes/{id}
Authorization: Bearer <token>

Orders

Lifecycle: pending_payment → paid → fulfilling → completed (or failed / cancelled / expired). After payment FEX issues the policy with Hollard. The order completes once the policy is issued.

POST /orders Bearer

Create an order from a quote and start payment.

Open payment.url. Sandbox-tier partners use FEX hosted sandbox pay; live-tier partners use MojoPay Omni when configured. Then poll or wait for webhooks. Configure your webhook URL under Partner Portal → Webhooks.

Headers

Idempotency-Key required
UUID recommended. Same key returns the same order.

Body parameters

quote_id required
string
From POST /quotes.
partner_reference required
string
Your reconciliation key.
payment_method optional
string
checkout (default) or collection.
success_url optional
url
Return URL after payment UX.
cancel_url optional
url
Cancel / abandon URL.
customer optional
object
Optional customer details.
metadata optional
object
Arbitrary partner metadata.
POST http://fex.mojo-pay.com/v1/orders
Request
{
  "quote_id": "QTE_…",
  "partner_reference": "INV-1001",
  "payment_method": "checkout",
  "success_url": "https://partner.example/success",
  "cancel_url": "https://partner.example/cancel",
  "customer": { "email": "customer@example.com" },
  "metadata": { "channel": "mobile_app" }
}
Response 201
{
  "id": "ORD_…",
  "object": "order",
  "status": "pending_payment",
  "partner_reference": "INV-1001",
  "currency": "GHS",
  "amount": "50.00",
  "amount_payable": "50.00",
  "product_id": "PRD_…",
  "payment": {
    "id": "CS_…",
    "method": "checkout",
    "status": "processing",
    "url": "https://omni.mojo-pay.com/pay/CS_…",
    "merchant_reference": "FEX-ORD_…-1"
  },
  "failure": null,
  "created_at": "…",
  "completed_at": null
}
GET /orders/{id} Bearer

Retrieve an order by public id.

Path parameters

id required
string
Order public id.
GET http://fex.mojo-pay.com/v1/orders/{id}
Request
GET /orders/{id}
Authorization: Bearer <token>
GET /orders Bearer

List up to 50 most recent orders for the partner.

Query parameters

status optional
string
Filter by order status.
GET http://fex.mojo-pay.com/v1/orders
Request
GET /orders
Authorization: Bearer <token>
Response 200
{
  "object": "list",
  "data": [
    { "id": "ORD_…", "object": "order", "status": "completed" }
  ]
}
POST /orders/{id}/cancel Bearer

Cancel an order when still cancellable (typically before payment completes).

Path parameters

id required
string
Order public id.
POST http://fex.mojo-pay.com/v1/orders/{id}/cancel
Request
POST /orders/{id}/cancel
Authorization: Bearer <token>

Webhooks

Configure a webhook URL per API client under Partner Portal → API & webhooks. FEX signs every delivery with FEX-Signature (HMAC-SHA256).

Verify signature

Header format:

FEX-Signature: t=<unix_timestamp>,v1=<hmac_sha256_hex>

Signed payload: {timestamp}.{raw_body} using your webhook_secret.

Event envelope
{
  "id": "EVT_…",
  "type": "order.completed",
  "api_version": "2026-06-01",
  "created": "2026-08-25T14:30:00+00:00",
  "data": {
    "object": {
      "id": "ORD_…",
      "object": "order",
      "status": "completed"
    }
  }
}

Event types

Type When
order.pending_payment Order created; customer should pay
order.paid Payment confirmed
order.fulfilling Provider fulfillment started
order.completed Terminal success
order.failed Terminal failure
order.cancelled Cancelled by partner or system

Respond with 2xx quickly. Delivery is at-least-once — dedupe on event id.

Errors

Failed responses use the standard envelope. Use error.code for handling and request_id when contacting support. Provider codes (provider_*) can also appear on a failed order as failure.code.

Error envelope

{
  "error": {
    "code": "validation_failed",
    "message": "Product fields failed validation.",
    "details": { "errors": { "amount": ["required"] } },
    "request_id": "req_…"
  }
}

Common codes

unauthorized not_found product_unavailable validation_failed quote_unavailable quote_expired invalid_state provider_not_found provider_error