Heads Up: Subscription Interval Values Differ Between the SDK and REST API
Heads Up: Subscription Interval Values Differ Between the SDK and REST API
Affects:
pay.subscriptions.create()· Version flagged: v1.0.72 · Status: Fix in pipeline
What's the issue?
We've identified a vocabulary mismatch between the Calmony Pay SDK client and the REST API for creating subscriptions.
The SDK's CreateSubscriptionParams type defines the interval field as:
interval: 'month' | 'year'
This follows Stripe's naming conventions. However, the REST API at POST /v1/subscriptions validates the same field using a server-side Zod enum:
z.enum(['monthly', 'annual'])
The values are different, and the API will reject the SDK's values outright.
What happens in practice?
If you use the SDK as documented and pass interval: 'month' or interval: 'year', the API will respond with:
{
"error": {
"type": "invalid_request_error",
"message": "Invalid interval value. Expected one of: monthly, annual."
}
}
This is a 400 Bad Request — the request never creates a subscription.
Affected code paths
| File | Issue |
|---|---|
src/lib/calmony-pay/client.ts | SDK types interval as 'month' | 'year' |
src/app/api/v1/subscriptions/route.ts | API validates interval as 'monthly' | 'annual' |
Workaround (until fixed)
Until the vocabulary is aligned in a follow-up release, bypass the SDK type for interval and pass the API-compatible values directly:
// ❌ Will cause a 400 error
await pay.subscriptions.create({
interval: 'month',
// ...
});
// ✅ Workaround — use the API's expected values
await pay.subscriptions.create({
interval: 'monthly' as any,
// ...
});
Alternatively, call the REST API directly with the correct values:
await fetch('/v1/subscriptions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
interval: 'monthly', // or 'annual'
// ...
}),
});
What's next?
A fix is in the pipeline to align both the SDK type definitions and the API validation schema to use a single, consistent set of values. We will update this page and the changelog once the fix is released.