Record a subscription
Records the latest state of a subscription the payment source manages, under the source's own id for it.
Idempotent on externalId and ordered by updatedAt: a state older than the recorded one is superseded and changes nothing. Only a payment source records purchases.
Guide: Payment sources
A project secret key: vh_sk_... for production, vh_sk_test_... for test. Keep it on your servers.
In: header
Path parameters
The project's id, proj_.... A secret key works only in the project it belongs to.
The id of the project's payment provider connection, pp_conf_....
The payment source's own id for the transaction or subscription; to request a refund, the charge's.
Request body
application/json
TypeScript definitions
Use the request body type in TypeScript.
The latest state of a subscription the payment source manages. It decides access; revenue comes only from the charges that name the subscription.
The buyer's distinct id. With customer as well, it identifies the source's customer as that person.
The buyer as the source's own customer; required without distinctId.
The source's key for the subscription product, as mapped to a product.
trialing starts a free trial for the current period; active keeps access through paid periods; past_due keeps access while the source retries the payment; canceled ends access at canceledAt (or updatedAt when it's left out); expired ends it at the current period's end.
Value in
- "trialing"
- "active"
- "past_due"
- "canceled"
- "expired"
The start of the current period, as an ISO 8601 timestamp.
The end of the current period, as an ISO 8601 timestamp.
Whether the subscription renews at the end of the current period; false cancels it at the period's end, true again resumes it.
When a canceled subscription's access ends, as an ISO 8601 timestamp; updatedAt when left out.
When the source last changed the subscription, as an ISO 8601 timestamp; an older update never overwrites a newer one.
production or test; defaults to production.
Examples
curl -X PUT "https://api.voidhash.com/api/v1/projects/proj_tz4a98xxat96iws9zmbrgj3a/payment-providers/pp_conf_m2c8v5n1x7z4q9w3e6r0t8y2/subscriptions/sub_ext_0042" \ -H "Authorization: Bearer vh_sk_..." \ -H "Content-Type: application/json" \ -d '{ "distinctId": "user_8231", "productKey": "pro-monthly", "status": "active", "currentPeriodStart": "2026-03-14T09:26:53.000Z", "currentPeriodEnd": "2026-04-14T09:26:53.000Z", "isAutoRenewing": true, "updatedAt": "2026-03-14T09:26:53.000Z" }'{ "id": "sub_ext_0042", "paymentProviderId": "pp_conf_m2c8v5n1x7z4q9w3e6r0t8y2", "status": "applied", "pendingReason": null, "subscriptionId": "sub_r8t2y6u0i4o9p3a7s1d5f9g3"}{ "error": { "type": "invalid_request", "code": "invalid_subscription", "message": "A subscription names its buyer with distinctId or customer.externalId" }}{ "error": { "type": "unauthenticated", "code": "invalid_api_key", "message": "This secret key is not valid." }}{ "error": { "type": "permission_denied", "code": "permission_denied", "message": "Insufficient permissions." }}{ "error": { "type": "not_found", "code": "payment_provider_not_found", "message": "This project has no payment provider pp_conf_k2v8d4m1x7c9b3n6q0w5e2r8.", "param": "paymentProviderId" }}{ "error": { "type": "conflict", "code": "payment_source_disabled", "message": "This payment source is disabled; enable it to record purchases." }}{ "error": { "type": "internal", "code": "internal_error", "message": "Something went wrong on our side. Try again, and contact support with the Request-Id header if it keeps failing." }}Response body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
Errors
| Status | type | code | When |
|---|---|---|---|
| 400 | invalid_request | invalid_subscription | For a state that cannot be recorded as sent. |
| 400 | invalid_request | payment_source_required | For a store. |
| 404 | not_found | payment_provider_not_found | For an unknown provider. |
| 409 | conflict | payment_source_disabled | For a disabled source. |
It can also fail with the errors every operation shares, such as unauthenticated; see Errors.
More in Payment sources
- Record a transaction
PUT - Refund a transaction
POST - Cancel a subscription
POST
Something wrong or missing on this page? Tell us by email or on Discord.