Skip to main content
Web payment reference
Updated over a week ago

Overview

The Web Payment integration allows you to use the payment provider of your choosing to manage subscription payments on the web. It works by you making requests to the Treefort API to manage users’ subscription state, and Treefort reaching out to a set of API endpoints implemented by you to fetch links to user checkout pages and billing portals, fetch subscription plan details, request cancellations, and validate promo codes.

Treefort API

Make requests to the Treefort API to manage a user’s subscription state. A subscription grants access to content as long as its deactivatedAt property is null. If a subscription’s canceledAt property is not null that means the user has opted to cancel their subscription and it shouldn’t renew at the end of the billing period, at which point your integration should set deactivatedAt to the current date. The currentPeriodEndsAt property should be the end date of the billing period the user has paid for. It’s up to you to update the currentPeriodEndsAt property at the end of each billing period when the user’s subscription renews. If your implementation is correct then for healthy, renewing subscriptions canceledAt and deactivatedAt will be null and currentPeriodEndsAt will always be a future date.

Subscription POST endpoint

Use this endpoint to create a subscription in the Treefort system. Use the value "webPayment" for the provider property in your request body. You can find complete documentation for the Treefort subscription POST endpoint here.

Subscription PATCH endpoint

Use this endpoint to update a subscription in the Treefort system. Use the value "webPayment" for the provider property in your request body. You can find complete documentation for the Treefort subscription PATCH endpoint here.

Your API

Treefort will make requests to your API to fetch subscription plan details, to fetch links to checkout pages and billing portals, to request cancellations, and to validate promo codes. The endpoints you must implement for the Web Payments integration are described below. Request and response schemas are defined in TypeScript.

Subscription plan endpoint

Treefort will use this endpoint to fetch details about a subscription plan from your API.

Method: POST

type RequestBody = { 
// The id of the subscription plan in the Treefort database
subscriptionPlanId: number
}

type ResponseBody = { 
subscriptionPlanId: number
// Whether the plan renews at intervals of months or years
interval: "month" | "year"
// The number of months/years in a single billing period (will
// usually just be one)
intervalCount: number
// Used for display in the app
trialLengthDays: number
// The number of days after currentPeriodEndsAt to wait before
// deactivating a subscription
gracePeriodDays: number
price: {
// Three letter ISO currency code, for example "USD"
currency: string
amount: number
// The number to divide amount by before formatting the currency. For
// example, if amount where 150 to represent $1.50 in USD, then
// divisor would be 100
divisor: number
}
}

Checkout session endpoint

Treefort will use this endpoint to fetch a link to a checkout page for a specific user. This link will be used in the checkout flow when the user subscribes and when they switch plans.

🚧 The link that you generate should be unique, unguessable, and should expire within 24 hours.

Method: POST

type RequestBody = { 
user: {
id: string
email: string
createdAt: string // A date
firstName?: string
lastName?: string
fullName?: string
data?: Record<string, unknown>
},
// The user's locale as an ISO language code like "fr" or "de-DE"
locale: string
// The id of the plan the user is trying to subscribe to
subscriptionPlanId: number
// The promo code, if any, that the user entered at checkout. If the
// promo code is invalid you should respond with a 400 status code
promoCode?: string
// Where you should redirect the user when checkout completes
successUrl: string
// Where you should redirect the user if they want to cancel the
// checkout flow
cancelUrl: string
}

type ResponseBody = { 
// The link that Treefort will redirect the user to for them to begin
// your checkout process
sessionUrl: string
}

Billing portal session endpoint

Treefort will use this endpoint to fetch a link to a billing portal for a specific user. The exact functionality of the billing portal is up to you, but it should at least allow users to manage their billing information.

🚧 The link that you generate should be unique, unguessable, and should expire within 24 hours.

Method: POST

type RequestBody = { 
user: {
id: string
email: string
createdAt: string // A date
firstName?: string
lastName?: string
fullName?: string
data?: Record<string, unknown>
},
// The user's locale as an ISO language code like "fr" or "de-DE"
locale: string
// Where to redirect the user to if you want to show a back link to the
// web app
backUrl: string
}

type ResponseBody = { 
// The link that Treefort will redirect the user to for them to manage
// their billing
sessionUrl: string
}

Cancel subscription endpoint

Treefort will use this endpoint to request that you cancel a user’s subscription. When you receive a cancellation request from Treefort you should make a request to the Treefort subscription PATCH endpoint described above to set the canceledAt property to the current date. Wait to respond with a success response to the cancellation request until you’ve received a success response from the PATCH endpoint.

Method: POST

type RequestBody = { 
userId: string
subscriptionPlanId: number
}

Promo code validation endpoint (optional)

This endpoint is optional, but if you choose to implement it then Treefort will use it to validate promo codes entered by the user on the subscriptions page in the app.

👉 Promo codes must only contain numbers and letters a-z. Codes that contain other characters will automatically be considered invalid. Your validation logic should be case insensitive.

Method: POST

type RequestBody = { 
// Will be undefined for unauthenticated users
userId?: string
// The ids of the subscription plans that the promo code must be valid
// for
subscriptionPlanIds: number[]
// The promo code. MUST be letters a-z and numbers, and validation
// MUST be case-insensitive
code: string
}

type ResponseBody = 
| {
code: string
type: "amount"
// See the explanation of the price property in the response
// returned by your subscription plan endpoint
amountOff: {
amount: number
currency: string
divisor: number
}
eligibleSubscriptionPlanIds: number[]
// Only used for the message displayed in the app to unauthenticated
// users. It's up to you to return the invalid response type if you
// don't want a signed in user to be able to use the code
firstTimeSubscribersOnly: boolean
}
| {
code: string
type: "percent"
eligibleSubscriptionPlanIds: number[]
firstTimeSubscribersOnly: boolean
percentOff: number
}
| {
type: "invalid"
}
Did this answer your question?