Sandbox Testing
Use the sandbox to test the complete recurring-payment flow without creating live charges.
Use the hosted-checkout card details listed under Recurring-payment sandbox cards. These cards are separate from the normal NGN S2S sandbox cards.
Test Checklist
- Use your SaySwitch test secret key.
- Create a test customer through the Customers API.
- Create an NGN recurring plan.
- Initialize a subscription with a unique
Idempotency-Key. - Open the returned
authorization_urlin a browser. - Complete the hosted card authorization and recurring-payment consent.
- Retrieve the subscription and confirm that its status becomes
active. - Confirm that your test webhook endpoint receives the relevant lifecycle event.
- Cancel the subscription and confirm the cancellation response and webhook.
Temporary certification note: Certification of some unattended recurring sandbox scenarios is still in progress. If a scheduled off-session recurring-token charge requests additional customer authentication, the charge attempt is recorded as failed and the subscription may move to
past_due.
1. Create a Test Customer
curl --request POST \
--url https://backendapi.sayswitchgroup.com/api/v1/customer \
--header "Authorization: Bearer YOUR_TEST_SECRET_KEY" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data '{
"email": "recurring-test@example.com",
"first_name": "Ada",
"last_name": "Okafor",
"phone": "2348012345678"
}'Save the returned customer_code.
2. Create an NGN Plan
Use daily only when you need the shortest publicly supported interval. The API does not provide an accelerated minute-based test interval.
curl --request POST \
--url https://backendapi.sayswitchgroup.com/api/v1/plan \
--header "Authorization: Bearer YOUR_TEST_SECRET_KEY" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data '{
"name": "Daily Sandbox Access",
"description": "Daily plan for recurring-payment testing",
"amount": 100,
"currency": "NGN",
"interval": "daily",
"invoice_limit": 2
}'Save the returned plan_code.
3. Initialize a Subscription
Use a new idempotency key for each subscription you intentionally create.
curl --request POST \
--url https://backendapi.sayswitchgroup.com/api/v1/subscription \
--header "Authorization: Bearer YOUR_TEST_SECRET_KEY" \
--header "Idempotency-Key: sandbox-recurring-001" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data '{
"customer": "CUS_customer_code",
"plan_code": "PLN_plan_code",
"return_url": "https://merchant.example/subscription/complete",
"metadata": {
"test_case": "sandbox-recurring-001"
}
}'Open the returned data.authorization_url and complete the hosted authorization flow using supported SaySwitch sandbox card details. Never place real card details in a sandbox request or in your server logs.
4. Retrieve the Subscription
curl --request GET \
--url https://backendapi.sayswitchgroup.com/api/v1/subscription/SUB_subscription_code \
--header "Authorization: Bearer YOUR_TEST_SECRET_KEY" \
--header "Accept: application/json"Confirm the subscription is active. Depending on the start date and initial charge result, inspect its next_charge_at, invoices, and attempts.
The return-page query parameters are not final confirmation. Use this API response and your signed webhook events to decide whether the subscription is active.
5. Observe Webhooks
Your test webhook URL can receive events such as:
subscription.initializedsubscription.activatedsubscription.authentication_requiredsubscription.charge_succeededsubscription.charge_failedsubscription.completedsubscription.cancelled
Verify each request using the test secret and public keys as described in Recurring Payment Webhooks.
6. Test Cancellation
curl --request POST \
--url https://backendapi.sayswitchgroup.com/api/v1/subscription/SUB_subscription_code/cancel \
--header "Authorization: Bearer YOUR_TEST_SECRET_KEY" \
--header "Accept: application/json"Confirm that the response status is cancelled, next_charge_at is null, and your webhook endpoint receives subscription.cancelled.
Troubleshooting
| Issue | What to check |
|---|---|
HTTP 401 | Confirm you are sending Authorization: Bearer YOUR_TEST_SECRET_KEY and that the key is valid. |
HTTP 422 for the customer | Create the customer with the same test key used for the subscription. |
HTTP 422 for the plan | Confirm the plan belongs to the same test account and its status is active. |
| Existing subscription returned | You reused an Idempotency-Key. This is expected for a retry; use a new key for a new subscription. |
| Authorization expired | Initialize a new subscription with a new idempotency key and complete checkout before its expiry. |
Subscription is past_due | Review the failed charge webhook and retrieve the latest subscription details. |
Do not modify database records or run internal server commands to force a billing date. Use the public daily interval for the shortest supported schedule.