Get Results
Retrieve assessment results via polling or webhooks.
After submitting an assessment, retrieve results by polling or receiving a webhook.
Option 1: Polling
Poll the job status endpoint until processing completes.
Endpoint
GET /api/v1/assess/{jobId}
Polling strategy
Poll every 10-15 seconds until status is completed or failed.
async function pollForResults(jobId, apiKey) {
const maxAttempts = 30; // 5 minutes at 10s intervals
for (let i = 0; i < maxAttempts; i++) {
const response = await fetch(
`https://oqui.io/api/v1/assess/${jobId}`,
{ headers: { Authorization: `Bearer ${apiKey}` } }
);
const data = await response.json();
if (data.status === 'completed') {
return data.result;
}
if (data.status === 'failed') {
throw new Error(data.error.message);
}
// Still processing, wait and retry
await new Promise(r => setTimeout(r, 10000));
}
throw new Error('Timeout waiting for assessment');
}
Status values
| Status | Meaning |
|---|---|
pending | Job queued, not yet started |
processing | Currently processing documents |
completed | Finished successfully, results available |
failed | Processing failed, error details available |
Option 2: Webhooks
Provide a webhook_url when submitting to receive results automatically.
Webhook payload
When processing completes, we POST to your webhook URL:
Success:
{
"event": "assessment.completed",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"assessment_id": "660e8400-e29b-41d4-a716-446655440001",
"status": "completed",
"external_reference": "loan-app-12345",
"completed_at": "2024-01-15T10:03:30Z",
"result": { ... }
}
Failure:
{
"event": "assessment.failed",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"assessment_id": "660e8400-e29b-41d4-a716-446655440001",
"status": "failed",
"external_reference": "loan-app-12345",
"error": {
"code": "BANK_STATEMENT_FAILED",
"message": "One or more bank statements failed to process",
"failed_documents": ["corrupted.pdf"]
}
}
Webhook signature
Webhooks include an X-Webhook-Signature header for verification:
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
Webhook retries
If your endpoint returns a non-2xx status, we retry:
- 3 retry attempts
- Exponential backoff (1min, 5min, 15min)
- After all retries fail, webhook is marked as failed
Result structure
Completed assessments include a comprehensive result object:
{
"period": {
"from": "2024-01-01",
"to": "2024-03-31",
"months_covered": 3,
"statement_count": 3,
"transaction_count": 245
},
"summary": {
"average_monthly": {
"recognized_income": 45000,
"gross_income": 52000,
"fixed_obligations": 12000,
"essential_expenses": 8000,
"external_debt": 5000,
"total_obligations": 25000,
"surplus": 20000,
"dti_ratio": 55.5
},
"dti_status": "elevated",
"income_stability": "stable"
},
"monthly_breakdown": [...],
"income_analysis": {...},
"obligations_analysis": {...},
"verification": {...},
"risk_indicators": {...},
"transactions": [...],
"affordability_rules_applied": {...}
}
Key result sections
| Section | Description |
|---|---|
period | Date range and document counts |
summary | Executive summary with averages and DTI |
monthly_breakdown | Month-by-month detail |
income_analysis | Income by category with haircuts |
obligations_analysis | Fixed and credit obligations |
verification | Cross-document verification results |
risk_indicators | Behavioral flags and credit issues |
transactions | All extracted transactions |
affordability_rules_applied | Rules used for calculation |
Processing status
Both polling and webhook responses include processing_status showing per-document status:
{
"processing_status": {
"bank_statements": [
{ "filename": "jan-2024.pdf", "status": "completed", "transaction_count": 85 },
{ "filename": "feb-2024.pdf", "status": "completed", "transaction_count": 72 }
],
"payslips": [
{ "filename": "payslip-jan.pdf", "status": "completed" }
],
"credit_report": { "status": "completed" },
"classification": { "status": "completed" },
"verification": { "status": "completed" }
}
}
Handling failures
When an assessment fails, the response includes error details:
{
"status": "failed",
"error": {
"code": "BANK_STATEMENT_FAILED",
"message": "Unable to extract transactions from statement",
"failed_documents": ["corrupted.pdf"]
}
}
Common error codes:
| Code | Meaning |
|---|---|
BANK_STATEMENT_FAILED | Could not process bank statement |
CLASSIFICATION_FAILED | Transaction classification failed |
PAYSLIP_FAILED | Could not process payslip |
CREDIT_REPORT_FAILED | Could not process credit report |
INSUFFICIENT_DATA | Not enough data for assessment |