API reference

Payments API

Move money against a funded account — one-off payment links, recurring collection schedules and ad-hoc repayments — then reconcile every movement through signed payment.* webhooks. Collections settle over open banking (PISP) so you never touch card or bank credentials.

Roadmap — not yet available. These endpoints do not exist yet and return 503 Service Unavailable. Documentation is provided so you can design against the planned shape. Build against the live token + MCP surface today; availability will be announced on the changelog.

The Payments API drives the money-in side of servicing: a borrower repaying their facility, an early settlement, or a scheduled instalment plan that mirrors the loan's repayment terms. Money-out (disbursement of approved funds) is handled separately and is not exposed on the partner ring. Every resource lives under the partner/v1 base URL and is authenticated with a bearer token.

Base URL
https://hub.credicorp.co.uk/partner/v1
Auth
OAuth 2.0 bearer token — scope payments:write for creation, payments:read for retrieval.
Rails
Open banking payment initiation (PISP) for collections; Faster Payments settlement.
Idempotency
Required on every write — send a unique Idempotency-Key header.

Amounts are integers in pence. A repayment of £500.00 is amount_pence: 50000. Currency is always GBP. Never send a decimal — the API rejects non-integer amounts.

Endpoints

MethodPathPurpose
POST/payments/linksCreate a hosted payment link for a one-off repayment.
POST/payments/schedulesCreate a recurring collection schedule against a mandate.
GET/payments/{id}Retrieve a single payment.
GET/paymentsList payments (filter by account_id, status).
GET/payments/schedules/{id}Retrieve a schedule and its upcoming collections.
POST/payments/{id}/refundReverse a settled payment.
DEL/payments/schedules/{id}Cancel an open-ended schedule (tombstoned, not destroyed).

A payment link returns a hosted pay.credicorp.co.uk URL you can email, SMS or embed. The borrower selects their bank, authenticates in their banking app, and the payment settles by Faster Payments. You receive a payment.paid webhook on settlement.

POST/partner/v1/payments/links
bash
curl -s https://hub.credicorp.co.uk/partner/v1/payments/links \
  -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: pl_3f9a1c" \
  -H "Content-Type: application/json" \
  -d '{
        "account_id": "acc_2WdR7yK",
        "amount_pence": 50000,
        "reference": "INV-2026-0481",
        "description": "June instalment",
        "redirect_url": "https://app.acme.co.uk/repay/done"
      }'
javascript
import Credicorp from '@credicorp/sdk';
const cc = new Credicorp({ token: process.env.CC_TOKEN });

const link = await cc.payments.links.create({
  account_id:   'acc_2WdR7yK',
  amount_pence: 50000,
  reference:    'INV-2026-0481',
  description:  'June instalment',
  redirect_url: 'https://app.acme.co.uk/repay/done'
}, { idempotencyKey: 'pl_3f9a1c' });

console.log(link.url); // → https://pay.credicorp.co.uk/l/9Lm…
php
use Credicorp\Client;

$cc = new Client(token: getenv('CC_TOKEN'));

$link = $cc->payments->links->create([
    'account_id'   => 'acc_2WdR7yK',
    'amount_pence' => 50000,
    'reference'    => 'INV-2026-0481',
    'description'  => 'June instalment',
], idempotencyKey: 'pl_3f9a1c');

echo $link->url;

Parameters

FieldTypeDescription
account_idstringreqFunded account the repayment is applied to.
amount_penceintegerreqAmount to collect, in pence. Must be > 0.
referencestringoptYour reference (≤18 chars). Echoed on the bank statement and every webhook.
descriptionstringoptShown to the payer on the hosted page.
redirect_urlstringoptWhere the payer returns after authorising. Falls back to your dashboard default.
expires_atstringoptRFC 3339 expiry. Default 7 days.

Response 201 Created

json
{
  "id": "pay_9Lm4Qx",
  "object": "payment",
  "account_id": "acc_2WdR7yK",
  "status": "pending",
  "amount_pence": 50000,
  "currency": "GBP",
  "reference": "INV-2026-0481",
  "url": "https://pay.credicorp.co.uk/l/9Lm4Qx",
  "expires_at": "2026-07-06T11:04:00Z",
  "created_at": "2026-06-29T11:04:00Z"
}

Create a collection schedule

A schedule sets up recurring collections — typically the repayment plan agreed at origination — against a payment mandate held on the account. Each due date generates a child payment which is initiated automatically; you are notified per instalment by payment.paid or payment.failed.

POST/partner/v1/payments/schedules
bash
curl -s https://hub.credicorp.co.uk/partner/v1/payments/schedules \
  -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: sch_88c0" \
  -d '{
        "account_id": "acc_2WdR7yK",
        "amount_pence": 41667,
        "cadence": "monthly",
        "start_date": "2026-07-15",
        "count": 12,
        "mandate_id": "mnd_7Hb2"
      }'

Parameters

FieldTypeDescription
account_idstringreqFunded account to collect against.
amount_penceintegerreqPer-instalment amount.
cadencestringreqweekly or monthly.
start_datestringreqFirst collection date (RFC 3339 date).
countintegeroptNumber of instalments. Omit for open-ended.
mandate_idstringoptExisting mandate. If absent, the first collection establishes one.

Response 201 Created

json
{
  "id": "sch_5Tk9Pa",
  "object": "payment_schedule",
  "account_id": "acc_2WdR7yK",
  "status": "active",
  "cadence": "monthly",
  "amount_pence": 41667,
  "remaining": 12,
  "next_collection": {
    "payment_id": "pay_A1c…",
    "due_date": "2026-07-15"
  }
}

Match the plan, not the calendar. Derive amount_pence and count from the account's repayment schedule (see Accounts roadmap) so collections stay in lock-step with the outstanding balance. A final “sweep” instalment squares any rounding remainder.

Payment statuses

A payment moves through a small, deterministic lifecycle. Drive your ledger from webhooks rather than polling — statuses are terminal once reached, except paid → refunded.

StatusWebhookMeaning
pendingCreated; payer has not yet authorised, or the due date has not arrived.
processingpayment.processingAuthorised and submitted to Faster Payments; awaiting settlement.
paidpayment.paidSettled and applied to the account balance.
failedpayment.failedBounced, cancelled or expired. See failure_reason.
refundedpayment.refundedA settled payment was reversed in full.

Failure reasons

CodeDescription
insufficient_fundsPayer's account lacked the balance.
payer_cancelledAuthorisation abandoned or declined in-app.
mandate_revokedThe collection mandate was withdrawn.
link_expiredHosted link reached expires_at unpaid.
bank_unavailableThe payer's bank could not be reached; safe to retry.

Refund a payment

POST/partner/v1/payments/{id}/refund

Reverses a settled payment over the same rails. Only full refunds are supported; the resulting credit is applied back to the account and a payment.refunded event is emitted.

bash
curl -s -X POST https://hub.credicorp.co.uk/partner/v1/payments/pay_9Lm4Qx/refund \
  -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: rf_001" \
  -d '{ "reason": "duplicate_collection" }'

Reconciliation

Every state change is delivered as a signed webhook, so your ledger never has to poll. Subscribe to the payment.* family and match each event to your records using the account_id plus your own reference. Events are HMAC-signed and retried with exponential back-off — verify the signature and de-duplicate on event.id.

webhook
{
  "id": "evt_Qm0v2",
  "type": "payment.paid",
  "created_at": "2026-06-29T11:09:42Z",
  "data": {
    "id": "pay_9Lm4Qx",
    "account_id": "acc_2WdR7yK",
    "reference": "INV-2026-0481",
    "amount_pence": 50000,
    "status": "paid",
    "settled_at": "2026-06-29T11:09:40Z"
  }
}
EventFires when
payment.processingPayer authorised; submitted to the rails.
payment.paidFunds settled and applied to the account.
payment.failedCollection bounced, expired or was cancelled.
payment.refundedA settled payment was reversed.
schedule.completedThe final instalment of a fixed schedule settled.

Treat webhooks as the source of truth, never the redirect. A payer returning to your redirect_url does not guarantee settlement — funds may still be processing. Only mark a repayment cleared on payment.paid. See Webhooks roadmap for signature verification and the full retry policy.

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": "validation_failed",
    "message": "The request failed validation.",
    "detail": [{ "field": "amount_pence", "reason": "min_value" }],
    "correlation_id": "cor_01J2K3M4N5P6Q7R8S9T0A1V2W3",
    "retryable": false
  }
}
codeHTTPWhen
validation_failed422A required field is missing or a value is out of range. detail[] carries per-field specifics.
conflict409Idempotency-Key reused with a different body, or illegal state transition.
not_found404No account or payment found for the supplied ID.
unauthenticated401Missing or invalid access token.
token_expired401Token has expired — refresh it and retry.
insufficient_scope403Token not granted payments:write (creation) or payments:read (retrieval).
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.


Related: Accounts roadmap for balances and repayment schedules, Webhooks roadmap for signed delivery, and Idempotency for safe retries.