Skip to main content

Payment Request Invalid

payment_request_invalid400

Billing · Affects all endpoints

The payment processor rejected the request as malformed. No charge was made.

What this means

We sent a payment request to the processor (Dodo) and it came back with an "invalid request" response — the request shape didn't match what the processor expected. The user was never charged. This is almost always a server-side issue on our end, not something the user can fix by retrying.

When you'll see this

  • A plan or product configuration on our side drifted from what the processor has registered.
  • A new field was added to the payment payload that the processor's current API version doesn't recognize.
  • A currency mismatch between our request and the processor's expected currency for the user's region.
  • A test/production environment mismatch (a sandbox payment payload sent to the live processor or vice versa).
Learn more about how this works

The processor returns this kind of rejection at the request validation layer, before any charge attempt. It's structurally a 4xx from the processor that we surface as a 400 from Asterwise. The distinguishing feature: the user did nothing wrong, the network is fine, the processor is up — but the shape of what we sent didn't pass schema validation on their end.

The most common gotcha: this error sometimes appears immediately after we ship a new plan or change pricing. It usually means we updated our side without updating the processor's product catalog. The fix is on us, not the user — but the user sees the error first.

Example response

{
"success": false,
"error": "payment_request_invalid",
"message": "Payment provider rejected the request as invalid.",
"details": [],
"retry_after": null,
"doc_url": "https://docs.asterwise.com/reference/errors/payment_request_invalid",
"request_id": "req_01HXYZABCDEFGH",
"timestamp": "2026-05-25T12:34:56Z"
}
NEW TO APIS?
Quick fix
  1. Don't retry — the same payload will keep being rejected.
  2. Refresh asterwise.com/dashboard and try the checkout flow from there (sometimes a stale browser session is involved).
  3. If it still fails, email [email protected] with the request_id. This is one of the few errors that almost always needs us to fix something on our side.
PRODUCTION ENGINEER
Recovery pattern

Not retriable. Surface clearly and route to support.

Python:

Production handler

import httpx
import logging

logger = logging.getLogger(__name__)

class PaymentRequestInvalidError(Exception):
"""Processor rejected the payment request shape. Server-side fix needed."""

def attempt_checkout(plan_id, base_url, headers):
response = httpx.post(
f"{base_url}/v1/billing/subscribe",
headers=headers,
json={"plan_id": plan_id},
timeout=15,
)
if response.status_code == 400:
body = response.json()
if body.get("error") == "payment_request_invalid":
logger.critical(
"Payment processor rejected request shape",
extra={"request_id": body.get("request_id")},
)
raise PaymentRequestInvalidError(
"Payment couldn't be processed. "
"Contact [email protected] with the request ID."
)
response.raise_for_status()
return response.json()

Avoid this error by

  • This isn't a client-side issue you can prevent — when it happens, it's a server-side mismatch we need to fix.
  • If you're building on top of Asterwise for your own customers, log occurrences with request_id so you can correlate with our resolution timeline.
  • Don't construct payment payloads yourself. Always use the official checkout flow from the dashboard.
  • After we resolve a known instance, the same plan_id will start working again — no client change needed on your end.