Getting started

Core concepts

The handful of ideas that the rest of the documentation assumes you know: the two API rings, the object graph that ties applications to decisions, payments and accounts, the sandbox/live split, our ID and money conventions, and the states a loan application moves through from creation to funding.

The Credicorp API is REST over HTTPS. Resources are JSON, requests are authenticated with bearer tokens, and the same object shapes come back from reads, writes and webhook payloads. Read this page once and the reference sections will feel familiar.

API rings

Every endpoint belongs to one of two rings. The ring is the first path segment after the host and it decides who may call the endpoint and how it authenticates.

RingAudienceAuthTypical use
public/v1End users & browsersOIDC user token (PKCE)“Sign in with Credicorp”, a borrower reading their own account, consented identity claims.
partner/v1Your backendOAuth client-credentialsCreating applications, reading decisions, taking payments, servicing funded accounts.

The two rings never share a token. A partner/v1 client-credentials token acts as your organisation and can see the applications and accounts you originated; a public/v1 token acts as a single signed-in person and is scoped to their own data. Most integrations live almost entirely in partner/v1; reach for public/v1 only when a real human is present and consenting. See OAuth 2.0 for both flows.

The ring is not a version label — v1 is the API version and is shared across rings. We add fields without bumping the version; breaking changes ship under a new version with a deprecation window announced in the changelog.

Core objects

Six resources carry almost all the weight. They form a chain: an application produces a decision, an accepted decision funds an account, and an account is repaid through payments. Identity sits alongside, attaching verified people to the borrower.

ObjectPrefixWhat it is
applicationapp_A request to borrow, for one UK incorporated entity. The entry point to lending.
decisiondec_The authoritative AI outcome for an application: approve / refer / decline, plus the offer and reasons.
accountacc_A funded loan. Holds the balance, schedule and servicing state once money is disbursed.
paymentpay_A movement of money — a disbursement out, or a repayment collected in via open banking.
identityidv_A verified person (a director or beneficial owner) attached to the borrowing entity.
eventevt_An immutable record of something that happened, delivered to your webhook endpoints.

Every object carries the same envelope fields: a string id, an object type, a created_at timestamp, and — where you supplied one — your reference. References are echoed verbatim onto child objects, so a reference you set on an application appears on its decision, account and payments, which makes correlation in your own systems trivial.

Environments

There are two fully isolated environments. They share the same code, the same object shapes and the same SDKs — only the host, your credentials and the data differ. Nothing crosses between them.

EnvironmentBase URLBehaviour
Sandboxhttps://sandbox.credicorp.co.ukDeterministic. No real money, no real identity checks. Decisions are driven by magic amounts and test company numbers.
Livehttps://api.credicorp.co.ukReal borrowers, real Companies House and identity checks, real disbursement and repayment.

Sandbox credentials are prefixed cid_sbx_ / csk_sbx_; live credentials use cid_live_ / csk_live_. Because the prefix is visible on the key, an accidental cross-environment call fails loudly at authentication rather than doing something surprising. Build and certify against sandbox, then change the base URL and credentials — no other code changes are needed to go live.

Identifiers & money

Object IDs are opaque, prefixed strings — never parse meaning out of the characters after the prefix, and never assume a length. Treat them as the canonical reference for retrieval and storage.

ID shape
<prefix>_<random>, e.g. app_8Kd2c9Qm. The prefix tells you the type.
Money
Always integer minor units (pence) in fields suffixed _pence. Never floats.
Rates
Basis points in fields suffixed _bps. 1490 means 14.90%.
Currency
GBP only. There is no currency field to set.
Timestamps
RFC 3339 / ISO 8601 in UTC, e.g. 2026-06-29T10:01:12Z.

Pence, not pounds. Sending "amount_pence": 25000 requests £250, not £25,000. The single most common integration bug is a missing factor of one hundred — assert it in your tests.

Conventions

The whole API follows a small set of rules, so once you have learned them for one endpoint they hold everywhere.

  • Authentication. Bearer token in the Authorization header on every request. No tokens in query strings.
  • Idempotency. Send an Idempotency-Key on every POST that creates or moves money. Retrying with the same key returns the original result instead of duplicating it — see Idempotency.
  • Pagination. List endpoints are cursor-based: pass limit and follow next_cursor. Never page by offset. See Pagination.
  • Errors. Standard HTTP status codes plus a typed JSON body with a stable code and a human message. See Errors.
  • Expansion. Related objects appear as IDs by default; add ?expand=decision to inline them in a single round trip.
  • Rate limits. Per-token, returned in RateLimit-* response headers. Back off on 429. See Rate limits.

A typed error body looks like this, and the code is safe to branch on in code:

json
// HTTP 422 Unprocessable Entity
{
  "error": {
    "code": "amount_below_minimum",
    "message": "amount_pence must be at least 100000 (£1,000).",
    "param": "amount_pence",
    "request_id": "req_2Kd9c5Qm"
  }
}

Quote the request_id when you contact support — it lets us trace the exact call in our logs.

Application lifecycle

An application moves through a defined set of states. Transitions are one-way except where noted, and every transition emits an event — react to those rather than polling.

StateMeaningEmits
createdOpen; awaiting applicant completion (identity, open banking, principals).application.created
submittedApplicant finished; queued for decisioning.application.submitted
in_reviewDecisioning is running (or a referral is being underwritten).
approvedApproved; an offer is attached to the decision.decision.completed
declinedDeclined, with reasons. Terminal.decision.completed
fundedOffer accepted and disbursed; an account now exists.application.funded
withdrawn / expiredCancelled by you, or timed out before completion. Terminal.application.withdrawn

The happy path is created → submitted → in_review → approved → funded. A referred decision keeps the application in in_review until a human underwriter resolves it, at which point a second decision.completed fires with the final outcome. Because declined, withdrawn and expired are terminal, your state machine never has to handle a resurrected application — start a fresh one instead.

With these concepts in hand, the Quickstart reads in minutes and the API reference is just detail. Model the lifecycle states in your own database from the start — it pays off the moment you handle a referral.