Challanwala logo
Challanwala
Challanwala API Docs
Testing

Testing Guide

Use the staging replica API, generate dummy keys, and configure staging webhooks.

What the testing API is

The testing environment is a staging-only replica of the Challanwala organization API. It mirrors the public contract, but uses deterministic dummy data and a simulated payment flow.

  • Host: https://cms-staging.challanwala.com
  • API root: /api/v1/staging
  • Auth type: bearer secret
  • Data source: dummy challans generated from the RC number you search
Testing only

Generate a staging API secret

This testing route is public and mints a dummy bearer secret for the staging Hono API. It never creates a production organization key.

The generated secret is shown once here and saved locally in this browser so you can reuse it while testing.

Staging key generation

Testing keys are public self-serve credentials intended only for the staging environment. They do not expose production organization data and they do not work against production routes.

POST/api/v1/staging/api-keys

Create a dummy staging bearer secret that can be used against the replica API.

Base URL
https://cms-staging.challanwala.com
Authentication
No authentication required
Access gate
Public staging helper route
cURL request
curl --request POST 'https://cms-staging.challanwala.com/api/v1/staging/api-keys' \  --header 'Content-Type: application/json' \  --data '{"name": "Partner QA Sandbox"}'
JavaScript request
const response = await fetch('https://cms-staging.challanwala.com/api/v1/staging/api-keys', {  method: 'POST',  headers: {    'Content-Type': 'application/json',  },  body: JSON.stringify({name: "Partner QA Sandbox"}),});const data = await response.json();console.log(data);
Example response
{"success": true,"message": "Organization API secret generated","data": {  "key": {    "id": "8c9d962c-56cb-4b5d-998c-5a2a23c07e71",    "name": "Partner QA Sandbox",    "keyPrefix": "cms_test_2b15d8d31",    "status": "ACTIVE",    "createdAt": "2026-05-14T09:32:00.000Z",    "maskedKey": "cms_test_2b15d8d31************************"  },  "apiSecret": "cms_test_2b15d8d3156f98f1c1234ab5678ef901234567"}}

Replica routes

The staging API includes the same primary business capabilities as production, plus testing-only webhook configuration helpers:

StatusMeaningNotes
GET/api/v1/staging/metadata/rc-typesLists supported RC types for testing searches.
GET/api/v1/staging/locationsReturns fixed organization-scoped city/state fixtures.
POST/api/v1/staging/challans/searchCreates or reuses deterministic dummy challans for the RC number.
POST/api/v1/staging/payment-linksReturns ACTIVE first, then the stored link transitions immediately to its final test status.
GET/api/v1/staging/payment-links/:idPoll the stored payment-link status after creation.
GET/api/v1/staging/webhook-configReads the current staging webhook configuration and recent deliveries.
PUT/api/v1/staging/webhook-configSets the staging webhook URL, activation state, and optional secret rotation.
POST/api/v1/staging/webhook-config/testTriggers a signed webhook.test event to your configured receiver.

Configure staging webhooks

Use the protected webhook-config routes after generating a staging key.

Public HTTPS endpoints only

The hosted staging API only accepts public HTTPS webhook URLs. Localhost, private-network addresses, link-local targets, and redirecting webhook URLs are rejected for security reasons.

PUT/api/v1/staging/webhook-config

Save a staging webhook URL, enable or disable delivery, and optionally rotate the webhook secret.

Base URL
https://cms-staging.challanwala.com
Authentication
Bearer YOUR_API_SECRET
Access gate
Bearer secret required
cURL request
curl --request PUT 'https://cms-staging.challanwala.com/api/v1/staging/webhook-config' \  --header 'Authorization: Bearer YOUR_API_SECRET' \  --header 'Content-Type: application/json' \  --data '{"webhookUrl": "https://example.com/challanwala/webhook","isActive": true,"rotateSecret": true}'
JavaScript request
const response = await fetch('https://cms-staging.challanwala.com/api/v1/staging/webhook-config', {  method: 'PUT',  headers: {    Authorization: 'Bearer YOUR_API_SECRET',    'Content-Type': 'application/json',  },  body: JSON.stringify({webhookUrl: "https://example.com/challanwala/webhook",isActive: true,rotateSecret: true}),});const data = await response.json();console.log(data);
Example response
{"success": true,"message": "Webhook configuration saved","data": {  "config": {    "id": "71414ce7-84da-43d6-bdb6-1c9fce1f9760",    "webhookUrl": "https://example.com/challanwala/webhook",    "isActive": true,    "createdAt": "2026-05-14T09:41:00.000Z",    "updatedAt": "2026-05-14T09:41:00.000Z"  },  "webhookSecret": "whsec_54123f6a8dc9eaf73125cda94c336d98c701d1"}}

If the callback is unsafe, the staging API rejects it before saving:

Unsafe webhook URL response
{"success": false,"message": "Webhook URL must be a public HTTPS endpoint","errors": [  {    "path": "webhookUrl",    "message": "Localhost and mDNS webhook targets are not allowed."  }]}
cURL request
curl --request POST 'https://cms-staging.challanwala.com/api/v1/staging/webhook-config/test' \  --header 'Authorization: Bearer YOUR_API_SECRET'
JavaScript request
const response = await fetch('https://cms-staging.challanwala.com/api/v1/staging/webhook-config/test', {  method: 'POST',  headers: {    Authorization: 'Bearer YOUR_API_SECRET',  },});const data = await response.json();console.log(data);
Example response
{"success": true,"message": "Webhook test event queued","data": {  "eventType": "webhook.test"}}

What webhook events fire in testing

The staging replica does more than store a webhook URL. It also emits predictable test events so you can validate your receiver end to end.

StatusMeaningNotes
POST /webhook-config/testwebhook.testUse this first to confirm your endpoint is reachable and your signature verification is working.
POST /challans/searchchallan_search.completed or challan_search.failedA normal RC search sends challan_search.completed. Reserved failure RC numbers send challan_search.failed.
POST /payment-linkspayment_link.created followed by a final payment eventStandard staging RC numbers emit payment_link.created and then payment_link.paid almost immediately.
Reserved payment RCspayment_link.failed or payment_link.expiredSTGPAYFAILED and STGPAYEXPIRE let you test alternate payment webhook branches deterministically.

Immediate paid flow in testing

For normal staging RC numbers, payment-link creation returns an ACTIVE response first for contract compatibility, but the stored link transitions to PAID immediately after creation. Your webhook receiver should therefore be ready to process payment_link.created and payment_link.paid back to back.

Recommended staging webhook test sequence:

  1. Generate a staging API key.
  2. Save a public HTTPS webhook URL with rotateSecret: true.
  3. Verify the returned whsec_... secret in your receiver.
  4. Trigger POST /webhook-config/test and confirm webhook.test.
  5. Run a challan search and confirm challan_search.completed.
  6. Create a payment link and confirm payment_link.created and the final payment event.

Simulated payments

Generated staging payment links use a real testing page under the same host. Opening the paymentUrl shows a branded result page, but no real money movement happens.

  • Standard RC numbers: create returns ACTIVE, then status lookup becomes PAID
  • STGPAYEXPIRE: create returns ACTIVE, then status becomes EXPIRED
  • STGPAYFAILED: create returns ACTIVE, then status becomes FAILED

Use the reserved testing inputs on the next page for predictable edge-case validation.

On this page