Quickstart
Go from a cold start to a live estate read in three calls: exchange your client credentials for an OAuth token, discover the tools your scopes unlock, then call the authenticated Model Context Protocol (MCP) endpoint — every route strictly read-only, no money moved and nothing mutated.
This walkthrough uses the partner/v1 ring, where server-to-server integrations live. The live surface today is a small, sharply-defined one: an OAuth 2.0 token plane and an authenticated, read-only MCP tier. Everything below runs against the hub issuer https://hub.credicorp.co.uk. You should be able to complete the whole flow in a few minutes with nothing but curl.
Read-only by contract. Every tool on this tier is a pure read — there is no write, no money movement and no decisioning override. Your token's audience is hub-partner, which the hub's internal write plane structurally rejects. The canonical, always-current reference is /partner/v1/auth.md, generated live from the scope vocabulary so it can never drift.
Transactional lending is on the roadmap. The POST /partner/v1/applications → AI decision → webhooks → payments flow described in the guides is not yet built — those routes currently answer 503 Service Unavailable. See Roadmap below. Build against the token + MCP surface today; we will announce the write plane on the changelog.
Before you start
You need a registered confidential client, which gives you a client_id and client_secret. Clients are provisioned out-of-band by the Credicorp operator — contact the developer team with your agent name and the least scope tier you need. Secrets are stored hashed and shown once; keep yours server-side, never in a browser or mobile binary.
Two client tiers are live: agent-staff (scopes: mcp.read account.read ops.read) and agent-owner (all scopes: mcp.read account.read ops.read owner.read). Request the tier that matches your use case; the walkthrough below uses the agent-staff tier with a minimal mcp.read ops.read subset.
- Issuer / base
https://hub.credicorp.co.uk- Token URL
https://hub.credicorp.co.uk/partner/v1/oauth/token- MCP endpoint
https://hub.credicorp.co.uk/partner/v1/mcp- Ring
partner/v1(server-to-server, read-only)- Grant
client_credentialsonly — no end-user login, no refresh token
The full live endpoint table:
| Purpose | Method + path | Auth |
|---|---|---|
| Authorization-server metadata (RFC 8414) | GET /.well-known/oauth-authorization-server | public |
| Protected-resource metadata (RFC 9728) | GET /.well-known/oauth-protected-resource | public |
| JWKS verification key (RFC 7517) | GET /partner/v1/oauth/jwks | public |
| Agent registration guide (markdown) | GET /partner/v1/auth.md | public |
| Token exchange (client_credentials) | POST /partner/v1/oauth/token | client secret |
| Token introspection (RFC 7662) | POST /partner/v1/oauth/introspect | client secret |
| Authenticated MCP (JSON-RPC 2.0) | POST /partner/v1/mcp | Bearer + scope |
| MCP server card probe | GET /partner/v1/mcp | public |
Export your credentials so the snippets below run verbatim:
export CC_CLIENT_ID="agent-staff" export CC_CLIENT_SECRET="b3f9a7c1d2e4…" export CC_BASE="https://hub.credicorp.co.uk"
1. Get an access token
Exchange your client credentials for a short-lived bearer token using the OAuth 2.0 client-credentials grant. Authenticate either with HTTP Basic (base64(client_id:client_secret)) or by passing the credentials in the POST body. The scope parameter is optional — omit it for your client's full grant, or pass a space-delimited subset for least privilege.
curl -s "$CC_BASE/partner/v1/oauth/token" \ -u "$CC_CLIENT_ID:$CC_CLIENT_SECRET" \ -d "grant_type=client_credentials" \ -d "scope=mcp.read ops.read"
curl -s "$CC_BASE/partner/v1/oauth/token" \ -d "grant_type=client_credentials" \ -d "client_id=$CC_CLIENT_ID" \ -d "client_secret=$CC_CLIENT_SECRET" \ -d "scope=mcp.read ops.read"
Credentials are read from the POST body or HTTP Basic only. Query-string grant_type, scope, client_id and client_secret are deliberately ignored, so secrets can never ride a URL or land in a proxy log.
Response 200 OK
{
"access_token": "eyJhbGciOiJFZERTQSIsImtpZCI6…",
"token_type": "Bearer",
"expires_in": 300,
"scope": "mcp.read ops.read"
}The token is an EdDSA-signed JWS (audience hub-partner), valid for five minutes. There is no refresh token in the client-credentials flow — simply re-request one on demand, and cache it until roughly the last minute of its life to stay clear of rate limits. Pass it as Authorization: Bearer <token> on every MCP call that follows — the snippets assume it is exported as $TOKEN. You can verify a token's signature against the published /partner/v1/oauth/jwks key set.
2. Discover the tools your scopes unlock
The MCP endpoint speaks JSON-RPC 2.0 over HTTP (MCP Streamable HTTP). Two ways to see what you can call: an unauthenticated server card probe, and an authenticated tools/list that returns exactly the tools your token's scopes permit.
curl -s "$CC_BASE/partner/v1/mcp"
Now the authenticated handshake and tool listing. initialize is the MCP protocol handshake; tools/list is scope-filtered against your bearer.
curl -s "$CC_BASE/partner/v1/mcp" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "id": 1, "method": "tools/list" }'
Response 200 OK
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{ "name": "decisioning_explanation", "description": "…" },
{ "name": "ops_queue_status", "description": "…" },
{ "name": "enquiry_list", "description": "…" }
]
}
}Every JSON-RPC reply is HTTP 200 with Cache-Control: no-store; the outcome (success or error) lives in the envelope. The three tools shown reflect the requested scope subset (mcp.read ops.read): mcp.read gives the floor read decisioning_explanation; ops.read adds the two operational queue reads. The agent-staff tier also carries account.read (PII reads — request that scope to unlock those tools). Owner-tier platform reads (owner.read) require the agent-owner client. The table below enumerates every scope and its tools.
Scopes & the tools they grant read-only
| Scope | Tools | What it grants |
|---|---|---|
mcp.read | decisioning_explanation | Floor scope. Handshake (initialize/ping), tools/list, and the non-PII recorded decision explanation. |
ops.read | ops_queue_status, enquiry_list | Operational reads — aggregate queue depth and the staff triage queue (non-PII, staff-tier). |
account.read | application_status, customer_summary, loan_status, loan_statement, behavioural_digest | PII reads, staff-tier. Every call is written to the audit chain. |
owner.read | platform_metrics, portfolio_overview, config_snapshot, ops_metrics | Owner-tier platform reads. Requires agent-owner client. The strongest standing partner grant. |
3. Call a tool
Invoke a tool with tools/call, naming it and passing its arguments. The tool's required scope is re-checked against your token before it runs. Here we read the recorded, deterministic decision explanation for an application reference — the floor mcp.read scope is enough.
curl -s "$CC_BASE/partner/v1/mcp" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "decisioning_explanation", "arguments": { "reference": "APP-4471" } } }'
Response 200 OK
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{ "type": "text", "text": "{ … pretty-printed JSON … }" }
],
"structuredContent": {
"reference": "APP-4471",
"score": 74,
"band": "B",
"recommendation": "approve",
"recommendation_wire": "approve",
"locked": false,
"reasons": ["returning_customer_auto_approve"],
"gates": { "hard": [], "divert": [] },
"thresholds": { "approve": 62, "decline": 35 }
},
"isError": false
}
}The same payload rides in both places: human-/log-friendly text in content, and a typed structuredContent an agent can consume directly. The full response also carries components (per-factor sub-scores and weights), rationale (deterministic staff narrative), and band_cutoffs. Reason codes are machine-readable slugs; the human wording is not surfaced here. Call a tool your token does not carry the scope for and you get a clean JSON-RPC error (insufficient_scope) with a WWW-Authenticate hint — nothing leaks.
Optional: introspect a token
Need to check a token's liveness, scopes or expiry (for example in a downstream service)? The RFC 7662 introspection endpoint is client-authenticated:
curl -s "$CC_BASE/partner/v1/oauth/introspect" \ -u "$CC_CLIENT_ID:$CC_CLIENT_SECRET" \ -d "token=$TOKEN"
An active token returns { "active": true, "scope": "…", "aud": "hub-partner", "exp": … }; an expired, revoked or unknown token returns { "active": false }.
Roadmap — transactional lending
The programmatic write plane — creating applications, reading AI decisions over the wire, subscribing to webhooks, and initiating payments — is planned but not yet available. The routes below currently return 503 Service Unavailable and are documented here only so you can design ahead.
| Planned route | Status |
|---|---|
POST /partner/v1/applications | roadmap — 503 |
GET /partner/v1/applications/{id}/decision | roadmap — 503 |
POST /partner/v1/webhook_endpoints | roadmap — 503 |
POST /partner/v1/payments | roadmap — 503 |
GET /partner/v1/events | roadmap — 503 |
Until it ships, the AI decision explanation is available read-only today through the decisioning_explanation MCP tool (Step 3). We will announce the write plane, its scopes and its webhook catalogue on the changelog.
Next steps
That is the whole live spine: token → discover → call. From here:
- Read the canonical reference.
/partner/v1/auth.mdis generated from the live scope vocabulary and always current. - Understand the model. Core concepts covers rings, scopes, the MCP tool tiers and the read-only contract.
- Explore the tools. Work through Sandbox & test data for safe references to exercise each MCP tool.
- Harden auth. Read OAuth 2.0 before requesting higher-tier scopes.
Request additional scopes or client provisioning from developers@credicorp.co.uk. Ask for the least tier that does the job — account.read and owner.read return real customer and platform data, and every account.read call is audited.
