All guides
Implementation guides

How to Implement Subscriptions with Tirdad

Follow one customer from plan selection to activation, a mid-cycle upgrade, renewal, payment recovery, and cancellation—and see which system owns every decision.

Updated 2026-08-15

Noura chooses Growth at SAR 299 a month. Twelve days later, her team needs Scale. At renewal, the card fails.

If your implementation reduces that journey to is_paid = true, it will break at the first change. A subscription is the agreement connecting time, access, price, invoices, and payment. This guide shows how to model that agreement without rebuilding billing inside your product.

Subscription lifecycle

A subscription is a state machine—not a paid checkbox.

Every state answers two questions: what may the customer use now, and what should happen next?

01

TRIAL

Evaluate

Expires or converts

02

ACTIVE

Use the plan

Renews or changes

03

PAST DUE

Recovery window

Payment retries

04

CANCELED

Access ends

History remains

A plan change updates the active subscription; it does not create a second one.

Start with the decisions code cannot make

Before opening an API reference, write down the commercial rules. These rules become your implementation contract.

DecisionExample for NouraWhy it matters
When access startsAfter the first payment succeedsPrevents unpaid access
Upgrade timingImmediatelyControls when Scale entitlements open
Upgrade chargeProrate the remaining 18 daysDetermines the next invoice
Downgrade timingAt period endAvoids removing paid access early
Failed-payment window7 daysDefines recovery access
CancellationEnd of current periodKeeps the promise already paid for

An API cannot decide whether a downgrade is immediate or scheduled. If the business leaves that ambiguous, the ambiguity moves into production.

Give every fact one owner

Your application, Tirdad, and the payment provider participate in the same journey. They should not all decide the same thing.

System boundary

One journey. Three systems. No duplicated truth.

YOUR APPLICATION

Owns the experience

Account and workspace
Plan-selection flow
Product access and messaging
TIRDAD

Owns the agreement

Plan and price version
Subscription state
Proration, invoice, balance
PAYMENT PROVIDER

Moves the money

Payment method
Authorization
Settlement or failure
Store Tirdad IDs locally. Do not rebuild Tirdad state as a collection of booleans.

When Noura subscribes, Tirdad needs to know which account belongs to her in your product, and your product needs to know which Tirdad subscription belongs to that account. That relationship keeps every plan change and renewal attached to the right customer.

In your applicationIn TirdadWhat connects them
Noura’s accountCustomer recordThe same customer even if the email changes
Her workspaceSubscriptionCurrent plan and renewal date
The plan she selectedAgreed priceThe price used on her invoices

Do not rely on email alone. Noura can change it; her account and subscription still represent the same relationship.

Create the commercial model before the subscription

Build the plan in this order:

  1. Define the features customers recognize.
  2. Add the entitlements and limits included in Growth.
  3. Attach the monthly or annual recurring price.
  4. Publish a version that new subscriptions can reference.

Do not overwrite Growth when its price changes. Publish a new price version. Noura’s historical invoices should still explain the agreement she bought, while new customers receive the new terms.

Activate from confirmed state—not browser navigation

Noura clicks Choose Growth. Your frontend begins the journey, but it must not be the authority that opens access.

Activation sequence

Noura chooses Growth. When should access open?

Noura
Your application
Tirdad
Payment provider
Choose Growth
Create customer + subscription
Authorize first payment
Payment confirmed
subscription.active
Check entitlements
Growth access + limits
Workspace ready
Open access from the subscription result or webhook—not from the browser returning to a success page.

The reliable flow is:

  1. Your backend creates or matches the Tirdad customer.
  2. It creates the subscription with an idempotency key.
  3. The payment provider returns the payment result to Tirdad.
  4. Tirdad moves the subscription to its confirmed state.
  5. Your application receives the result or webhook, then asks for entitlements.

Why not trust the success page? The customer may close the tab before it loads. A malicious request may call it directly. The payment may also finish after the browser leaves. Subscription state must survive all three.

Make webhook handlers boring

Webhooks arrive more than once, sometimes out of order. Treat that as normal.

For each event:

  • verify the signature;
  • store the event ID before applying its effect;
  • ignore an event already processed;
  • compare versions or timestamps before replacing newer state;
  • fetch the current subscription when the local view is uncertain.

The event says something changed. The subscription record tells you what is true now.

Change the plan, not the identity

On day 12, Noura upgrades from Growth to Scale. Keep the same customer and subscription. Change the commercial terms attached to it.

Mid-cycle plan change

Growth becomes Scale on day 12. What changes immediately?

01

Growth

Day 1 → 12

Already earned

Tirdad calculates the unused Growth value and remaining Scale value
02

Scale

Day 12 → 30

New access

01One active subscription
02New entitlements now
03Proration on the invoice
04Full Scale renewal next cycle

After Tirdad confirms the change, your product refreshes the entitlements. That lets Scale access open immediately without teaching your application how to calculate unused Growth value, remaining Scale value, tax, or invoice balance.

For a downgrade, the same request can schedule the new plan for the next renewal. Noura keeps what she already paid for, and the future change remains visible and reversible.

Decide what a failed payment means for access

At renewal, Noura’s card fails. Three facts now coexist:

  • the renewal invoice is unpaid;
  • the subscription is in recovery;
  • your policy may allow seven more days of access.

Do not compress those facts into active = false. A payment failure is not necessarily a cancellation.

StateProduct behaviorCustomer message
ActiveNormal accessNext renewal date
Past due, in recoveryAccess based on your policyPayment failed; update the method
RecoveredNormal accessPayment received
CanceledRemove access at the agreed timeAccess end date

Tirdad owns the invoice and subscription state. Your application turns that state into the right product behavior and a clear next step.

Test time, retries, and failure

The happy path proves almost nothing. Before launch, verify these moments:

  • the create request times out, then retries with the same idempotency key;
  • the activation webhook arrives twice;
  • an older event arrives after a newer one;
  • an upgrade happens exactly at the billing boundary;
  • the upgrade payment fails;
  • renewal fails, then succeeds on retry;
  • cancellation is scheduled, then reversed;
  • historical invoices keep their original price version.

The implementation is ready when you can answer one question for every transition: which system decides the truth, and how does every other system learn it?

Model one subscription lifecycle. Do not spread it across a payment flag, a plan string, and a cancellation date that can disagree.