TPP-Led Flow 8 min read
You collect quote inputs, KYC, and surface the LFI’s hosted payment URL to the customer inside your own app. Document delivery also lives with you. The LFI handles underwriting, payment hosting, and policy issuance; your TPP is the customer-facing surface for everything else.
TPP-Led flow
Same as LFI-Led for quote creation
Obtain a Client Credentials token (insurance scope) and POST the quote request exactly as in LFI-Led. The mode is not declared on Create Quote — it’s determined by the LFI’s response to PATCH Accept.
Accept and discover PolicyIssuanceAllowed
Customer picks a quote; PATCH it with the accept data and your Subscription.Webhook. The LFI’s response signals whether the flow is TPP-Led: a 200 response with data.PolicyIssuanceAllowed means you are responsible for the steps listed as true.
{
"data": {
"PolicyIssuanceAllowed": {
"CustomerVerification": true,
"Payment": true,
"PolicyDocuments": true
}
}
}
All three flags true is the full TPP-Led mode. You MUST honour the declaration — do not perform a step set to false even if you can technically do so.
Collect KYC and submit to the LFI
After ApplicationPending arrives, collect the customer’s KYC in your app (see User Journeys — KYC capture for the screens to present). Submit by PATCHing the same quote endpoint a second time with the gathered data.
{
"Data": {
"PolicyStartDate": "2026-06-01",
"PolicyHolder": {
"EmiratesId": "784-1990-XXXXXXX-X",
"EmiratesIdExpiryDate": "2030-01-15",
"FullName": { "en": "Aisha Al Marri" },
"DateOfBirth": "1990-05-12",
"Address": {
"AddressLine": ["Villa 12, Street 5"],
"PostCode": "12345",
"TownName": "Dubai",
"CountrySubDivision": "Dubai",
"Country": "AE"
}
},
"AdditionalDeclarations": {
"NoClaimsLastFiveYears": true
}
}
}
The body conforms to the sector’s accept-quote schema. Required fields vary by sector — consult the OpenAPI spec. If KYC fails, you receive 400 with a descriptive message; surface it to the customer and allow retry.
Redirect the customer to the LFI-hosted payment URL
The LFI processes KYC asynchronously and, on success, emits ApplicationApproved with a BrokerInstructions[].Url pointing at its hosted payment page.
{
"QuoteStatus": "ApplicationApproved",
"BrokerInstructions": [
{
"ActionRequired": "Customer must complete premium payment at the LFI-hosted payment page.",
"Url": "https://pay.examplelfi.ae/checkout/sess-c93e1f4a"
}
]
}
Redirect the customer to BrokerInstructions[0].Url. They pay on the LFI’s page; the LFI redirects them back to a return URL you nominated when configuring your webhook or out-of-band with the LFI.
Do not cache, log, or replay the URL. If the customer abandons and returns, request a fresh URL by asking the LFI to re-emit (typically via your support process or by re-triggering the flow). The LFI will emit a new PaymentRequired event.
Issue the policy
After payment confirmation (which you can correlate with the customer’s return from the LFI’s payment page or by waiting for the LFI’s next status event), call POST /{type}-insurance-policies with the QuoteId. The body is similar to the KYC submission but represents the formal policy creation request.
The LFI runs its issuance and responds 201. The InsurancePolicyId and policy documents arrive in the subsequent PolicyIssued event — not in this response body.
Verify and surface documents to the customer
In TPP-Led mode the PolicyIssued event carries every customer-facing document the LFI would normally deliver itself. Verify each Hash against the decoded Content before presenting to the customer.
{
"QuoteStatus": "PolicyIssued",
"Documents": [
{
"Type": "Policy Booklet",
"FileName": "policy-booklet.pdf",
"ContentType": "application/pdf",
"Content": "JVBERi0xLjQKJeLjz9MKMyAwI...",
"HashType": "SHA256",
"Hash": "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918"
},
{
"Type": "Terms & Conditions",
"FileName": "terms.pdf",
"ContentType": "application/pdf",
"Content": "JVBERi0xLjQKJeLjz9MKMyAwI...",
"HashType": "SHA256",
"Hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
]
}
Hash verification
import { createHash } from 'node:crypto'
async function verifyDocument(doc: {
Content: string
Hash: string
HashType: string
}): Promise<boolean> {
if (doc.HashType !== 'SHA256') {
throw new Error('Unsupported HashType: ' + doc.HashType)
}
const bytes = Buffer.from(doc.Content, 'base64')
const computed = createHash('sha256').update(bytes).digest('hex')
return computed === doc.Hash
}
import base64, hashlib
def verify_document(doc: dict) -> bool:
if doc["HashType"] != "SHA256":
raise ValueError(f"Unsupported HashType: {doc['HashType']}")
raw = base64.b64decode(doc["Content"])
return hashlib.sha256(raw).hexdigest() == doc["Hash"]
If a document’s computed hash does not match the supplied Hash, treat the document as corrupt or tampered. Do not surface it to the customer. Log the x-fapi-interaction-id from the event delivery, raise a support ticket including that ID and the QuoteId, and request the LFI re-emit the event.
Surface final policy state and reconcile commission
On Completed, finalise the policy in your records, surface it as live to the customer, and reconcile any commission against the event’s Commission block. PaymentMethod: ThroughAPIHub means the Hub will route payment to you; the commission and timing are governed by the AlTareq Commercial and Pricing Model.
No further events follow. You can let the subscription lapse, or explicitly PATCH the quote with IsActive: false if you prefer to clean up — though no further events would be sent regardless.
