Integration Guide

Integrating statement upload + webhook notification + client analysis retrieval.

Proceed with the integration steps below.

📘

Info

Authentication

  • All calls to the endpoints will require an API Key in the Header
  • It should be provided asX-API-Key: YOUR_API_KEY, which you can get from your dashboard or upon request via email to [email protected]

Base URL

  • All endpoints will be appended to this URL https://service.cladfy.com/v1/

Content type:

  • Multipart endpoint: multipart/form-data
  • Base64 endpoint: application/json

Get supported providers (required before upload)

The provider field is required for both upload endpoints.

Fetch supported provider codes first:

curl --request GET "https://service.cladfy.com/v1/providers/" \
	--header "X-API-Key: YOUR_API_KEY"

Use one of the returned provider code values (for example mpesa) in upload requests.

Integrate in a few minutes

1. Create client first

Before uploading a statement, create a client and store the returned id as client_id.

Example request

curl --request POST "https://service.cladfy.com/v1/clients" \
	--header "X-API-Key: YOUR_API_KEY" \
	--header "Content-Type: application/json" \
	--data '{
		"first_name": "Jane",
		"last_name": "Doe",
		"phone_number": "0712345678",
		"email": "[email protected]",
		"national_id": "12345678"
	}'

Example response

{
	"id": 12345,
	"first_name": "Jane",
	"last_name": "Doe",
	"full_name": "Jane Doe",
	"phone_number": "0712345678",
	"email": "[email protected]",
	"upload_url": null
}

2. Upload statement (multipart)

Endpoint: POST /documents

Required fields:

  • file
  • client_id
  • provider

Optional fields:

  • password
  • webhook
  • national_id

Copy/paste request

curl --request POST "https://service.cladfy.com/v1/documents" \
	--header "X-API-Key: YOUR_API_KEY" \
	--form "file=@/path/to/statement.pdf" \
	--form "client_id=12345" \
	--form "provider=mpesa" \
	--form "password=" \
	--form "webhook=https://partner.example.com/cladfy/webhook" \
	--form "national_id=12345678"

Example response

{
	"id": 98765,
	"url": "https://.../documents/1739....pdf",
	"client_id": 12345,
	"provider": "mpesa",
	"status": "analyzing",
	"created_at": "2026-03-26T11:20:31.910000"
}

3. Upload statement (base64 JSON)

Endpoint: POST /documents/base64

Required fields:

  • file_base64
  • filename
  • client_id
  • provider

Optional fields:

  • password
  • webhook
  • national_id

Copy/paste request

curl --request POST "https://service.cladfy.com/v1/documents/base64" \
	--header "X-API-Key: YOUR_API_KEY" \
	--header "Content-Type: application/json" \
	--data '{
		"file_base64": "JVBERi0xLjcKJc...",
		"filename": "statement.pdf",
		"client_id": "12345",
		"provider": "mpesa",
		"password": null,
		"webhook": "https://partner.example.com/cladfy/webhook",
		"national_id": "12345678"
	}'

Example response

{
	"id": 98766,
	"url": "https://.../documents/1739....pdf",
	"client_id": 12345,
	"provider": "mpesa",
	"status": "analyzing",
	"created_at": "2026-03-26T11:22:02.102000"
}

4. Webhook payload contract (analysis complete)

If you provide webhook in upload, your endpoint will receive a POST after analysis is done.

Webhook request body

{
	"document_id": 98766,
	"client_id": 12345,
	"business_id": 678
}

Your webhook must return

  • HTTP 200 (or any 2xx) quickly.

Important

  • Webhook receipt means analysis is complete and results are ready to fetch.
  • Polling is an optional fallback only.

5. Fetch analysis results by client id

After webhook, fetch results from:

  • GET /clients/analysis_results
  • Include header: X-Client-Id: <client_id>

Copy/paste request

curl --request GET "https://service.cladfy.com/v1/clients/analysis_results" \
	--header "X-API-Key: YOUR_API_KEY" \
	--header "X-Client-Id: 12345"

Example response shape

{
	"document": {
		"id": 98766,
		"status": "analyzed",
		"provider": "mpesa",
		"currency": "KES",
		"created_at": "2026-03-26T11:22:02.102000",
		"last_analyzed_on": "2026-03-26T11:22:12.991000"
	},
	"client": {
		"id": 12345,
		"full_name": "Jane Doe",
		"national_id": "12345678"
	},
	"summary": {
		"total_in": 125000.0,
		"total_out": 98000.0,
		"transaction_count": 152,
		"zero_balance_rate_percentage": 7.2
	},
	"transactions": [
		{
			"id": 1,
			"type": "credit",
			"amount": 1500.0,
			"date": "2026-03-01 00:00:00",
			"narration": "Deposit",
			"balance": 3500.0,
			"currency": "KES"
		}
	],
	"cashflow": {
		"monthly": [],
		"averages": {}
	},
	"spending": {},
	"loans": {
		"summary": {},
		"aggregate": {}
	}
}

6. Results payload mapping (quick reference)

  • document.* → statement metadata + analysis status
  • client.* → client identifiers
  • summary.* → totals and quality indicators
  • transactions[] → normalized transaction ledger
  • cashflow.monthly / cashflow.averages → trend and averages
  • spending → categorized spending output
  • loans.summary / loans.aggregate → loan behavior output

7. Credit scoring

Request a credit score for a client after analysis is complete.

Option A — GET by client ID in the URL

curl -X GET "https://service.cladfy.com/v1/clients/{client_id}/scoring" \
  -H "X-API-Key: YOUR_API_KEY"

Option B — POST with client ID in the body

curl -X POST "https://service.cladfy.com/v1/clients/scoring" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"cladfy_client_id": 42}'

Success response (200)

{
  "score": 720,
  "risk_tier": {
    "tier": "Good",
    "color": "#3b82f6",
    "min_score": 680,
    "risk": "Low risk"
  },
  "features": { "...": "..." },
  "scored_at": "2026-03-26T10:30:00"
}

Risk tiers: Excellent (780-850) · Good (680-779) · Fair (560-679) · Poor (400-559) · Very Poor (300-399)

Error responses

StatusMeaning
404Client not found
403Client belongs to another business
503Scoring service temporarily unavailable — retry later

Scoring history

Retrieve all past scores for audit/compliance:

curl -X GET "https://service.cladfy.com/v1/clients/{client_id}/scoring/history?limit=50" \
  -H "X-API-Key: YOUR_API_KEY"

Note: Each scoring call triggers a live prediction — it is not a cached read. Use the history endpoint if you only need previously computed scores.


8. Optional fallback: poll document status

If webhook delivery fails, you may poll:

  • GET /documents/{document_id}/status

Status values:

  • analyzing
  • analyzed
  • failed

9. Fetch client documents

List all documents (statements) uploaded for a client, with URL, status, and metadata.

curl -X GET "https://service.cladfy.com/v1/clients/{client_id}/documents" \
  -H "X-API-Key: YOUR_API_KEY"

Example response (200)

[
  {
    "document_id": 98766,
    "url": "https://.../documents/1739....pdf",
    "name": "statement.pdf",
    "password": null,
    "results": "...",
    "status": "analyzed",
    "props": "...",
    "client_id": 12345,
    "created_at": "2026-03-26T11:22:02.102000",
    "type": null,
    "provider": "mpesa",
    "currency": "KES"
  }
]
FieldDescription
document_idUnique document ID
urlDownload URL for the uploaded PDF
statusanalyzing, analyzed, or failed
providerProvider code used at upload (e.g. mpesa)
currencyDetected currency
created_atUpload timestamp
ErrorMeaning
404Client not found
403Client belongs to another business

10. Repeat.

  1. Go to step 1 to create more clients.
  2. Or go to step 3 to upload additional statements to the same client.
  3. Or go to Step 5 / Step 6 to fetch the analyzed data belonging to specific clients.