Skip to content

VRP Billing — Merchant Integration Guide (v1)

Audience: merchants integrating GoCardless with VRP Billing to receive real‑time payment updates and reconcile payouts.

Last updated: 11 Aug 2025


1) Quick start

  1. Get your credentials from VRP Billing support (issued out of band):

  2. Webhook Path Token: e.g. abc123...

  3. Webhook Secret: a long random string
  4. (Optional) API Key for server‑to‑server calls: prefix.secret (request or rotate via support)
  5. Create a Webhook Endpoint in GoCardless Dashboard (Developers → Webhook endpoints):

  6. URL: Use https://api.vrpbilling.com/v1/vrp/webhook/<token>/ when handling live traffic with your production GoCardless credentials, or https://sandbox.api.vrpbilling.com/v1/vrp/webhook/<token>/ when testing with sandbox credentials.

  7. Secret: paste your Webhook Secret exactly.
  8. Send a test webhook from the Dashboard and confirm VRP Billing shows the event in Activity / Webhooks.
  9. (Optional) Pull data via API using your API key once support has provisioned it for you.

Hands-on quickstart * Import the Postman collection at postman/vrp-billing.postman_collection.json together with the matching environment file postman/vrp-billing.postman_environment.json to run the health check, consent, payment, and webhook verification calls end-to-end. * If you prefer VS Code, open docs/quickstart.http with the REST Client extension for the same sequence of requests. Update the shared variables at the top of the file (API key, mandate details, webhook secret, etc.) before executing each request.


2) Concepts

  • Events → Webhooks: GoCardless emits events (e.g., payments.paid_out, payments.failed, mandates.cancelled). It pushes them to your webhook endpoint as a JSON body { "events": [...] }.
  • Security: Every webhook includes both a Webhook-Signature and a GoCardless-Signature header. Their value is the lowercase hexadecimal HMAC‑SHA256 of the exact, raw request body using your merchant Webhook Secret. VRP Billing validates either header using your Webhook Secret (see verification logic).
  • Idempotent: The same event may be retried; VRP Billing de‑duplicates by GoCardless event ID.

3) Configure your webhook in GoCardless

  1. In GoCardless DashboardDevelopersWebhook endpointsCreate.
  2. Set URL to the VRP Billing host for your environment: https://api.vrpbilling.com/v1/vrp/webhook/<token>/ for production (live GoCardless credentials) or https://sandbox.api.vrpbilling.com/v1/vrp/webhook/<token>/ for sandbox testing. Replace <token> with your Webhook Path Token from VRP Billing.
  3. Paste your Webhook Secret.
  4. Save.
  5. Click the endpoint → Send test webhook. Choose a resource/action (e.g., payments → paid_out). VRP Billing will reply 204 No Content on success and show the event in your Activity log.

Important • The URL must be HTTPS. • If you rotate the Webhook Secret in GoCardless, update it in VRP Billing immediately to avoid 403/498 signature failures. • VRP Billing must have both the path token and the shared secret stored for your merchant; without the secret, _verify_gc_signature will reject requests with 403.


4) What VRP Billing receives

HTTP Request (from GoCardless to VRP Billing):

POST /v1/vrp/webhook/<token>/ HTTP/1.1
Content-Type: application/json
User-Agent: gocardless-webhook-service/1.x
Webhook-Signature: <hmac-sha256-hex>
GoCardless-Signature: <hmac-sha256-hex>

{
  "events": [
    {
      "id": "EV123...",
      "created_at": "2025-08-11T12:00:00.000Z",
      "resource_type": "payments",
      "action": "paid_out",
      "links": { "payment": "PM123...", "payout": "PO123..." },
      "details": {
        "origin": "gocardless",
        "cause": "payment_paid_out",
        "description": "Payment has been included in a payout",
        "scheme": "bacs"
      }
    }
  ]
}

VRP Billing behaviour

  • Verifies Webhook-Signature/GoCardless-Signature against your Webhook Secret.
  • Validates the path token (/webhook/<token>/) and resolves your merchant.
  • Persists the raw body + parsed JSON.
  • Processes each event exactly once (idempotency by event ID).
  • Responds 204 No Content on success.

Failure responses (for visibility during testing):

  • 400 – malformed JSON or missing token
  • 403/498 – signature invalid (secret mismatch or secret missing); ensure both the path token and webhook secret are configured in VRP Billing.

Sample payload and local verification

When testing locally you can save a sample webhook payload and compute the signature exactly how GoCardless does:

cat <<'EOF' > payload.json
{
  "events": [
    {
      "id": "EV1234567890",
      "created_at": "2025-08-11T12:00:00.000Z",
      "resource_type": "payments",
      "action": "paid_out",
      "links": {
        "payment": "PM1234567890",
        "payout": "PO1234567890"
      },
      "details": {
        "origin": "gocardless",
        "cause": "payment_paid_out",
        "description": "Payment has been included in a payout",
        "scheme": "bacs"
      }
    }
  ]
}
EOF

WEBHOOK_SECRET="your-shared-secret"
EXPECTED_SIGNATURE=$(openssl dgst -sha256 -mac HMAC -macopt key:"$WEBHOOK_SECRET" payload.json | awk '{print $2}')

curl -X POST https://sandbox.api.vrpbilling.com/v1/vrp/webhook/<token>/ \
  -H 'Content-Type: application/json' \
  -H "Webhook-Signature: $EXPECTED_SIGNATURE" \
  --data-binary @payload.json
  • openssl outputs the HMAC in lowercase hexadecimal, which must match the value GoCardless will place in both signature headers.
  • Sending the payload without a configured webhook secret results in a 403 because _verify_gc_signature rejects the missing header; make sure VRP Billing support has stored both the path token and secret for your merchant.

5) Typical events to expect

  • payments.created / submitted / confirmed / failed / charged_back / paid_out
  • mandates.created / active / cancelled / expired
  • payouts.paid (plus payments.paid_out for each included payment)

Use these to update your own systems (e.g., mark invoices as paid on payments.paid_out, pause service on mandates.cancelled).


6) Testing options

  • Dashboard “Send test webhook”: quick, no code required.
  • Scenario Simulators (Dashboard → Developer tools): trigger specific flows (e.g., payment fails, chargeback, paid out).
  • GoCardless CLI (advanced):
# In one terminal, listen to events locally
$ gc listen

# In another, trigger a test event
$ gc trigger payment_paid_out

Tip: In Sandbox, you can retry any historical webhook from the Dashboard if you want VRP Billing to re‑process it.


7) Create a VRP payment (API)

Use the consent's mandate ID to create individual payments once your customer has authorised the VRP.

POST https://api.vrpbilling.com/v1/vrp/payment/
Content-Type: application/json
X-Api-Key: pk_live_abcd.zyxw-123...

{
  "gc_mandate_id": "MD0123...",
  "amount_minor": 1299,
  "currency": "GBP",
  "metadata": {
    "invoice": "INV-10045",
    "attempt": 1
  }
}

Notes

  • Either gc_mandate_id or mandate_id must be supplied alongside amount_minor.
  • metadata is optional but, when provided, must be an object whose keys are ≤ 50 characters and whose values are strings ≤ 500 characters. Boolean and numeric values are converted to strings automatically.
  • VRP Billing always sets a purpose metadata value of "VRP payment" and, when available, a billing_request reference used for cap checks.

The response includes the GoCardless payment ID and initial status:

{
  "payment_id": "PM0123...",
  "status": "pending_submission"
}

Use your live API key with https://api.vrpbilling.com/v1 when processing real payments. For sandbox testing, swap the host to https://sandbox.api.vrpbilling.com/v1 and authenticate with the sandbox API key issued by VRP Billing support (typically prefixed pk_test_).

8) Pulling data from VRP Billing (API)

Use the API Key issued by VRP Billing support in the X-Api-Key header: X-Api-Key: <prefix>.<secret>. Requests that send the key in Authorization or any other header are rejected.

List payments (example)

GET https://api.vrpbilling.com/v1/vrp/payments/?status=paid_out&updated_after=2025-08-01T00:00:00Z
X-Api-Key: pk_live_abcd.zyxw-123...

200 OK

{
  "results": [
    {
      "id": 4812,
      "gc_payment_id": "PM0123...",
      "status": "paid_out",
      "amount_minor": 1299,
      "currency": "GBP",
      "gc_mandate_id": "MD0123...",
      "metadata": {"invoice": "INV-10045"},
      "updated_at": "2025-08-11T13:21:42Z"
    }
  ],
  "next": null
}

Fetch a single payment

GET https://api.vrpbilling.com/v1/vrp/payments/PM0123.../
X-Api-Key: pk_live_abcd.zyxw-123...

Filtering & pagination: All list endpoints support common filters like status, updated_after, and standard cursor pagination (next URL). Exact options may vary by deployment. Use sandbox credentials with https://sandbox.api.vrpbilling.com/v1 when querying test data.


9) Operational guidance

  • Retries: If VRP Billing returns a non‑2xx status, GoCardless will automatically retry deliveries. You can also manually Retry a specific webhook from the Dashboard.
  • Latency: Webhooks should be acknowledged quickly; VRP Billing processes heavy work asynchronously.
  • Rotation: Rotate your Webhook Secret periodically. Update the value in both the Dashboard and VRP Billing.
  • Security: Keep all credentials secret; never email them. The webhook URL must be HTTPS. If you use IP allowlists or mTLS on your side, coordinate with support. Request any API key changes through support rather than the console.

10) Troubleshooting

  • I get 403/498 Invalid Signature

  • The Webhook Secret in GoCardless doesn’t match the one stored in VRP Billing (or you pasted with extra spaces). Rotate/reset the secret and try again.

  • I get 400 Missing token

  • Ensure the URL path includes your token: /v1/vrp/webhook/<token>/.

  • I get 2xx but don’t see data

  • Check the event action you sent (e.g., payments.paid_out) and filters on your report/API call (e.g., status).

  • Duplicate events

  • Safe to retry; VRP Billing de‑duplicates per event ID.


11) Support

  • Sandbox onboarding & credentials: your VRP Billing contact
  • Secret rotation or API key reset: request via support
  • Status page / health: contact VRP Billing support for the latest status page URL for your deployment.

12) Copy‑paste snippets

cURL — test your API key

curl -H "X-Api-Key: <prefix>.<secret>" \
     -H "Accept: application/json" \
     "https://api.vrpbilling.com/v1/vrp/payments/?limit=1"

Swap the host to https://sandbox.api.vrpbilling.com/v1 and use your sandbox API key (e.g., pk_test_...) when validating against the sandbox environment.

Python — simple poller

import os, time, requests
API = os.environ["VRP_API_BASE"]
KEY = os.environ["VRP_API_KEY"]  # 'prefix.secret' issued by support
params = {"updated_after": "2025-08-01T00:00:00Z"}
headers = {"X-Api-Key": KEY}
while True:
    r = requests.get(f"{API}/v1/vrp/payments/", params=params, headers=headers, timeout=20)
    r.raise_for_status()
    data = r.json()
    for p in data.get("results", []):
        print(p["gc_payment_id"], p["status"], p.get("metadata", {}))
    params["updated_after"] = data.get("latest_updated_at", params["updated_after"])  # if provided
    time.sleep(30)

End of guide.