Teduh Khairat Partner API · v1

Developer Documentation

API-first integration for takaful providers, partner organisations, e-Khairat / SPJM, payment gateways and accounting systems.

REST · JSONOAuth2 client credentialsVersioned /v1SandboxRate limitsIdempotencySigned webhooks

Base URL & environments

EnvironmentBase URLNotes
Sandboxhttps://teduhkhairat.my/api/v1Client IDs prefixed tk_test_; demo data only.
Productionhttps://api.teduhkhairat.my/v1Issued after partner onboarding & security review.

This is a demonstration environment. All member, claim and payment data is fictitious.

Authentication

Exchange your client credentials for a short-lived bearer token (1 hour). Send it as Authorization: Bearer <token> on every request.

curl -X POST https://teduhkhairat.my/api/v1/oauth/token \
  -H "Content-Type: application/json" \
  -d '{"grant_type":"client_credentials","client_id":"tk_test_…","client_secret":"sk_test_…","scope":"members:read claims:read"}'

{ "access_token": "…", "token_type": "Bearer", "expires_in": 3600, "scope": "members:read claims:read" }

Scopes

ScopeGrants
members:readList and read members within your organisation scope
members:writeRegister members (status PENDING_PAYMENT until first payment)
certificates:readVerify takaful certificate status
claims:read / claims:writeRead claims; update claim status & settlement (takaful providers)
payments:read / payments:writePayment history; bulk import from legacy systems

Partner clients bound to an organisation only ever see that organisation's data.

Rate limits

Each client has a per-minute limit (shown in the console). Responses include X-RateLimit-Limit. Exceeding it returns 429 TOO_MANY_REQUESTS; retry with exponential backoff.

Idempotency

For every POST, send a unique Idempotency-Key header. Repeating a request with the same key returns the original result (header Idempotent-Replay: true) and never creates duplicates.

Errors

HTTP/1.1 403
{ "error": "insufficient_scope", "message": "insufficient_scope" }
StatusMeaning
400Validation error (invalid_phone, invalid_ic, …)
401invalid_client / invalid_token
403insufficient_scope
404Not found or outside your scope
409Conflict, e.g. member_exists
429Rate limited

Versioning

The major version is in the path (/v1) and echoed in X-API-Version. Additive changes ship without notice; breaking changes get a new major version with at least 6 months' overlap.

Members

GET/v1/members?updated_since=2026-01-01members:read
GET/v1/members/{member_no}members:read
POST/v1/membersmembers:write
curl -X POST https://teduhkhairat.my/api/v1/members \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -H "Idempotency-Key: 8f1c2d6e-…" \
  -d '{"name":"Ahmad bin Ali","ic":"800101-10-1234","phone":"0123344556","state":"Selangor","scheme":"SKM-KWP"}'

{ "data": { "member_no": "TDH-2026-000215", "status": "PENDING_PAYMENT" } }

Certificates

GET/v1/certificates/{certificate_no}certificates:read
{ "data": { "certificate_no": "TKF-88231045", "member_no": "TDH-2025-000128", "scheme": "Pelan Teduh Keluarga",
  "benefit_amount": 10000, "provider": "Amanah Takaful Berhad", "status": "IN_FORCE", "valid_until": "2027-08-02T…" } }

Claims

GET/v1/claims?status=SUBMITTEDclaims:read
POST/v1/claims/{ref}/statusclaims:write
{ "status": "SETTLED", "settled_amount": 8500, "reason": "Approved by claims committee" }
// status: UNDER_REVIEW | PENDING_INFO | SETTLED | REJECTED

Webhooks & signatures

Register an HTTPS endpoint per client. Events: member.activated, payment.succeeded, case.created, case.verified, claim.created, claim.updated. Failed deliveries retry with backoff for 24 hours.

Each delivery carries X-Teduh-Signature: t=<unix>,v1=<hex>, an HMAC-SHA256 of "<t>.<raw body>" using your webhook secret. Reject requests older than 5 minutes.

// Node.js verification
const [t, v1] = header.split(',').map(p => p.split('=')[1]);
const expected = crypto.createHmac('sha256', WEBHOOK_SECRET).update(`${t}.${rawBody}`).digest('hex');
const ok = crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected)) && Date.now() / 1000 - Number(t) < 300;

Live example: /api/v1/webhooks/signature-example

Powered by Khairat MyKasih · DKSB · Sandbox credentials are issued from the Teduh console (API & Integrations).