API reference

Decisioning API

Credicorp's decision engine is AI-led and authoritative. When an application is submitted it returns an outcome — approved, referred or declined — with indicative pricing and machine-readable reason codes, usually within a few seconds.

Roadmap — not yet available. The REST endpoints below do not exist yet and return 503 Service Unavailable. Decision data is available today via the decisioning_explanation MCP tool (live, mcp.read scope). The REST surface documented here is planned; availability will be announced on the changelog.

A decision is read-only: you do not create it, the engine produces exactly one per application. Read it via the MCP tool today or, once available, via the REST endpoints below (a read grant will be required). The most reliable way to consume an outcome is the decision.completed webhook; the endpoints below let you fetch or reconcile on demand.

Endpoints

MethodPathPurpose
GET/applications/{id}/decisionThe decision for one application.
GET/decisions/{id}Retrieve a decision by its own id.
GET/decisionsList & filter decisions.

Retrieve a decision

GET/partner/v1/applications/{id}/decision

Returns the decision attached to an application. Before the engine resolves, this returns 404 with code not_found — prefer the webhook over polling.

bash
curl https://hub.credicorp.co.uk/partner/v1/applications/app_8Kd2c9Qm/decision \
  -H "Authorization: Bearer $TOKEN"
php
$decision = $cc->applications->decision('app_8Kd2c9Qm');

if ($decision->outcome === 'approved') {
    $apr = $decision->apr; // e.g. 14.9
}
javascript
const decision = await cc.applications.decision('app_8Kd2c9Qm');

if (decision.outcome === 'approved') {
  const { apr, offer } = decision; // indicative pricing
}

Response 200 OK

json
{
  "id": "dec_5Tg9Hb2P",
  "object": "decision",
  "application_id": "app_8Kd2c9Qm",
  "outcome": "approved",
  "offer": {
    "amount_pence": 2500000,
    "term_months": 12,
    "apr": 14.9,
    "monthly_repayment_pence": 224170,
    "total_repayable_pence": 2690040,
    "is_indicative": true
  },
  "reasons": [
    { "code": "affordability_ok", "category": "affordability" },
    { "code": "credit_ok", "category": "credit" }
  ],
  "expires_at": "2026-07-13T10:00:03Z",
  "decided_at": "2026-06-29T10:00:03Z"
}

Response fields

FieldTypeDescription
outcomeenumapproved, referred or declined. See Outcomes.
offerobject | nullPresent when approved. Null for referred / declined.
offer.aprnumberIndicative representative APR as a percentage, e.g. 14.9.
offer.is_indicativebooleantrue until the credit agreement is signed; final terms are confirmed at acceptance.
reasons[]arrayStructured reason codes — always populated, including on approval.
expires_atstringWhen an approved offer lapses if not accepted (RFC 3339).
decided_atstringWhen the engine resolved the outcome.

Outcomes

OutcomeMeaning & next step
approvedAn offer is available at the returned offer.amount_pence / apr. Present it, then take acceptance — on signature the application moves toward funded.
referredThe engine deferred to a human underwriter. No action needed; it resolves to approved or declined later and fires a second decision.completed event. Typically within one business day.
declinedNo offer. Inspect reasons to explain the outcome to the applicant. A new application may be made after a cooling-off period.

Indicative APR & offer

The apr on an approved decision is indicative until the customer accepts and signs the credit agreement. It is derived from the modelled risk of the entity, the requested amount_pence and term_months, and current pricing. Re-pricing can occur if material new information surfaces at acceptance (for example a fresh adverse filing), in which case offer.is_indicative stays true and the final figures arrive on the funded account. Always render the offer object verbatim rather than recomputing repayments yourself — the engine accounts for fees and rounding to the penny.

Reason codes

Every decision carries one or more reasons. Each has a stable code and a category so you can group them in your UI. Treat the set as additive — new codes may appear within v1; branch on the ones you recognise and fall back to the human-readable message otherwise.

CodeCategoryMeaning
affordability_okaffordabilityModelled serviceability supports the request.
affordability_lowaffordabilityServiceability below threshold for the requested amount.
credit_okcreditCredit profile within appetite.
credit_adversecreditAdverse markers (CCJ, default) outside appetite.
thin_filecreditInsufficient trading history to model reliably.
banking_data_insufficientaffordabilityOpen-banking coverage too short to assess cashflow.
director_riskidentityOfficer screening raised a flag requiring review.
ineligible_entityeligibilityNot a UK incorporated company or LLP.
amount_exceeds_limiteligibilityRequest above the entity's modelled exposure ceiling.
manual_review_requiredpolicyPolicy routed the case to an underwriter (drives referred).

List decisions

GET/partner/v1/decisions

Cursor-paginated, newest first. Filter by outcome and decided_after for reconciliation or analytics.

bash
curl "https://hub.credicorp.co.uk/partner/v1/decisions?outcome=approved&limit=50" \
  -H "Authorization: Bearer $TOKEN"

Don't poll in a tight loop. Subscribe to decision.completed; the webhook carries the full decision body and fires the instant the engine resolves — including the second time, when a referred case is settled by an underwriter.

The decision is authoritative: there is no partner override to flip an outcome, and money only ever moves through the Payments roadmap resource after an offer is accepted. Test every branch deterministically with the scenario companies in Sandbox & test data.


Errors

All errors from this endpoint use the standard hub error envelope. Branch on code for precise handling; quote correlation_id when contacting support.

json
{
  "error": {
    "code": "not_found",
    "message": "The requested resource was not found.",
    "correlation_id": "cor_01J2K3M4N5P6Q7R8S9T0A1V2W3",
    "retryable": false
  }
}
codeHTTPWhen
not_found404No decision exists for the supplied ID, or it is not visible to this client.
decision_locked423The decision is locked — only an owner-sudo release can move it.
unauthenticated401Missing or invalid access token.
token_expired401Token has expired — refresh it and retry.
insufficient_scope403Token not granted the scope this endpoint requires.
rate_limited429Request rate over the quota; honour retry_after_ms and Retry-After. See Rate limits.
internal_error500Unexpected fault on our side. Safe to retry idempotent calls with back-off; quote correlation_id to support.
service_unavailable503Temporary maintenance or overload. Retry with back-off; check status.

The full error code list and all envelope fields are on the Errors page.