Sandbox live

Errors

v1 responses use a stable envelope. Every response also has request_id and an X-Request-Id header.

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid provider checkout payload",
    "details": {
      "missing_fields": ["student.email"]
    },
    "request_id": "req_3f9c2a1b8e7d6c5a4b3d2e1f"
  },
  "request_id": "req_3f9c2a1b8e7d6c5a4b3d2e1f"
}

Send your own id with X-Request-Id when correlating logs. Otherwise StudentPay generates req_….

Authentication

Code HTTP When
MISSING_API_KEY 401 Authorization header missing or empty
INVALID_API_KEY 403 Bearer token is not a recognised provider key
PROVIDER_KEY_MISMATCH 403 Key does not match provider.provider_code

Validation

Code HTTP When
VALIDATION_ERROR 400 Required fields missing or invalid (create or confirm)

Create details may include missing_fields and invalid_fields (for example pricing.course_price, plan.first_payment_date).

Confirm requires checkout.checkout_token, checkout.opportunity_id, checkout.dda_id, payment.payment_method, payment.first_payment_date, payment.deposit_confirmed: true, and all three declaration booleans true.

Checkout token

Confirm verifies the DDA setup JWT (checkout.checkout_token).

Code HTTP When
EXPIRED_CHECKOUT_TOKEN 401 Token expired
INVALID_CHECKOUT_TOKEN 401 Token missing, malformed, or not a valid setup token

Token / identifier mismatches on confirm return HTTP 403 with a string message, for example:

  • The Opportunity ID does not match the checkout token.
  • The direct debit authority ID does not match the checkout token.
  • The provider code does not match the checkout token.

On the v1 confirm route those string errors are mapped to error.code: INTERNAL_ERROR while the HTTP status stays 403. Treat the status and message as authoritative. This mapping is a known product gap, not a dedicated mismatch code.

Not found

Code HTTP When
PROVIDER_NOT_FOUND 404 Unknown or unusable provider_code on create
CHECKOUT_NOT_FOUND 404 Checkout not found for this provider (GET), or confirm cannot load the checkout / authority

Checkout state

Code HTTP When
DIRECT_DEBIT_SETUP_INCOMPLETE 409 Confirm called before setup complete. May include billing_request_status and mandate_status
CONFLICT 409 Confirm identifiers do not match the stored checkout (provider order id, checkout id, or DDA / opportunity pairing)

DIRECT_DEBIT_SETUP_INCOMPLETE is not “not Authorised”. Wait until GET shows setup_complete: true.

Create does not return an idempotency-conflict error. A repeated create reuses the existing checkout. See Idempotency.

Routing and server errors

Code HTTP When
METHOD_NOT_ALLOWED 405 Wrong HTTP method, or confirm without {checkoutId} in the path
INTERNAL_ERROR 500 Unexpected failure
INTERNAL_ERROR 403 Confirm token / identifier mismatch (see Checkout token). HTTP 403, not 500

Configuration

GET /v1/environment reports missing configuration by variable name in readiness.missing_required. It does not return secret values.

If GoCardless is not configured, hosted setup cannot start. Check payment_processor_status on the environment endpoint before you send payers to setup_url.