VoidhashDocs
DevelopersHelp centerGuidesAPI reference
Dashboard
Get started
Introduction
Quickstart
How Voidhash works
Glossary
Versions and releases
Concepts
Teams, projects and environments
API keys
Products and perks
Offers
Subscription lifecycle
People and identity
Events
Features
Paywalls in your app
Feature flags and A/B tests
Paywall components
Push notifications
Ad attribution in your app
Client SDKs
React Native
Swift
Kotlin
Web
Your backend
Node.js
PHP
Go
Rust
Other languages
Payment sources
Forward store notifications
Developer tools
CLI
MCP server
Query analytics with VoidQL
Payment sources
Transaction fields
Report subscriptions
Build a provider endpoint

Report subscriptions

Report a payment source's subscription payments and state, so renewals, trials and cancellations decide access.

A subscription from a payment source has two parts, and you report both. Its payments are charges that each pay for one period and book revenue. Its state decides access and carries no money.

Report the payments

Send each charge to the transactions endpoint, as in Report a payment, with subscriptionId, periodStart and periodEnd. The first starts the subscription, later ones renew it, and the first paid period after a trial converts the trial.

Report the state

Send the latest state to the subscriptions endpoint whenever it changes:

curl -X PUT "https://api.voidhash.com/api/v1/projects/$VOIDHASH_PROJECT_ID/payment-providers/$PAYMENT_SOURCE_ID/subscriptions/sub_9" \
  -H "Authorization: Bearer $VOIDHASH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "distinctId": "user_123",
    "productKey": "pro_monthly",
    "status": "active",
    "currentPeriodStart": "2026-10-01T00:00:00Z",
    "currentPeriodEnd": "2026-11-01T00:00:00Z",
    "isAutoRenewing": true,
    "updatedAt": "2026-10-01T00:00:05Z"
  }'
statusEffect
trialingA free trial for the current period.
activeAccess continues. With isAutoRenewing: false, it ends at the period's end; true again resumes renewal.
past_dueAccess continues while your provider retries the payment.
canceledAccess ends at canceledAt, which defaults to updatedAt.
expiredAccess ends at the end of the current period.

updatedAt is when your provider last changed the subscription, not when your server received the event. A state older than the one Voidhash holds is ignored, so order doesn't matter. The response has status applied (with the Voidhash subscriptionId), superseded by a newer state, or pending with the same pendingReason values as payments; charge_not_recorded waits for the first paid period's charge.

From your provider's webhooks, report a charge before the subscription state it changes, and map your provider's statuses onto these five explicitly; they rarely match one to one. See Translate your provider's webhooks.

Refund a subscription payment

Report the refund like any other, with refundsTransactionId; see Refunds. It returns the payment's revenue but doesn't change the state. If the refund also ends the subscription, report canceled too.

Next steps

  • Payment sources
  • Cancel and refund from Voidhash
  • Subscription lifecycle

Something wrong or missing on this page? Tell us by email or on Discord.

PreviousTransaction fieldsNextBuild a provider endpoint

On this page

Report the paymentsReport the stateRefund a subscription paymentNext steps