{
"grant_type": "client_credentials",
"client_id": "fex_…",
"client_secret": "…"
}
{
"access_token": "…",
"token_type": "Bearer",
"expires_in": 1200
}
Partner API Product guide
Hollard motor, home and travel policies — quote a premium, collect payment, and FEX issues the policy.
http://fex.mojo-pay.com/v1
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.
POST /oauth/token.GET /catalog/products?category=insurance_general and read each input_schema (fields differ a lot between motor, home and travel).payment.url.order.completed or order.failed.| Product | Name | Provider | Required fields | Lookup |
|---|---|---|---|---|
PRD_HI_HOMEhi-home-policy |
Hollard Home Policy | Hollard Insurance | begin_date end_date home_address |
— |
PRD_HI_MOTORhi-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_TRAVELhi-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.
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.
| 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. |
{
"grant_type": "client_credentials",
"client_id": "fex_…",
"client_secret": "…"
}
{
"access_token": "…",
"token_type": "Bearer",
"expires_in": 1200
}
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.
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.hi-home-policy): send home_estimated_value, home_content_listing (list of {item_name, price_ghs}), or both.hi-travel-policy): trip length days is 1–92, plus passport and emergency-contact details.GET /v1/catalog/products?category=insurance_general
{
"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}
Authorization: Bearer <token>
{
"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"
}
A quote locks the price for the fields you send. Every field must satisfy the product input_schema.
{
"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"
}
}
{
"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}
Authorization: Bearer <token>
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.
{
"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" }
}
{
"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}
Authorization: Bearer <token>
GET /orders
Authorization: Bearer <token>
{
"object": "list",
"data": [
{ "id": "ORD_…", "object": "order", "status": "completed" }
]
}
POST /orders/{id}/cancel
Authorization: Bearer <token>
Configure a webhook URL per API client under Partner Portal → API & webhooks. FEX signs every delivery with FEX-Signature (HMAC-SHA256).
Header format:
FEX-Signature: t=<unix_timestamp>,v1=<hmac_sha256_hex>Signed payload: {timestamp}.{raw_body} using your webhook_secret.
{
"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"
}
}
}
| 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.
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": {
"code": "validation_failed",
"message": "Product fields failed validation.",
"details": { "errors": { "amount": ["required"] } },
"request_id": "req_…"
}
}
unauthorized
not_found
product_unavailable
validation_failed
quote_unavailable
quote_expired
invalid_state
provider_not_found
provider_error