Moosyl logo

Subscriptions

Manage recurring billing with products, prices, customers, and subscriptions

Overview

Moosyl Subscriptions lets you set up recurring billing for your customers. The model is built around four core resources:

  • Product — what you sell (e.g. "Pro Plan")
  • Price — how much and how often (e.g. 1000 MRU / monthly)
  • Customer — who is paying, identified by your own user ID
  • Subscription — a customer subscribed to a price, with automatic billing cycles

All subscription endpoints require a secret API key.

1. Create a Product

A product represents your offering. You can manage products from the dashboard or via the API.

const res = await fetch("https://api.moosyl.com/products", {
  method: "POST",
  headers: {
    Authorization: process.env.MOOSYL_SECRET_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "Pro Plan",
    description: "Full access to all features",
  }),
});

const { data: product } = await res.json();
// product.id → use this to create prices

2. Create a Price

Each product can have up to one price per billing interval (weekly, monthly, yearly). Amounts are in MRU (smallest unit).

const res = await fetch("https://api.moosyl.com/prices", {
  method: "POST",
  headers: {
    Authorization: process.env.MOOSYL_SECRET_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    productId: product.id,
    amount: 1000,
    interval: "monthly",
  }),
});

const { data: price } = await res.json();
// price.id → use this when creating subscriptions

3. Create a Customer

Customers are identified by an externalUserId — this should be the user ID from your own system. Each external user ID is unique per organization.

const res = await fetch("https://api.moosyl.com/customers", {
  method: "POST",
  headers: {
    Authorization: process.env.MOOSYL_SECRET_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    externalUserId: "user_abc123",
    phone: "+22212345678", // optional
  }),
});

const { data: customer } = await res.json();

4. Create a Subscription

Subscribe a customer to a price. The subscription starts immediately by default.

const res = await fetch("https://api.moosyl.com/subscriptions", {
  method: "POST",
  headers: {
    Authorization: process.env.MOOSYL_SECRET_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    customerId: customer.id,
    priceId: price.id,
  }),
});

const { data: subscription } = await res.json();

Create by External User ID

You can also create a subscription using the external user ID directly. If the customer doesn't exist yet, it will be created automatically.

const res = await fetch("https://api.moosyl.com/subscriptions/by-external-user", {
  method: "POST",
  headers: {
    Authorization: process.env.MOOSYL_SECRET_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    externalUserId: "user_abc123",
    priceId: price.id,
    phone: "+22212345678", // optional, used if creating a new customer
  }),
});

Trial Periods

You can start a subscription with a trial. During the trial, no invoices are generated.

body: JSON.stringify({
  customerId: customer.id,
  priceId: price.id,
  trial: true,
  trialPeriod: "1_week", // "1_week", "1_month", or "1_year"
})

Or set an explicit trial end date:

body: JSON.stringify({
  customerId: customer.id,
  priceId: price.id,
  trial: true,
  trialEnd: "2025-06-01T00:00:00Z",
})

Subscription Statuses

StatusDescription
trialingIn trial period, no billing yet
activeActively billing on schedule
past_duePayment failed, awaiting retry
pausedTemporarily paused
cancelledCancelled, no further billing
expiredReached expiration date
pending_cancellationWill cancel at end of current period

Cancel a Subscription

await fetch(`https://api.moosyl.com/subscriptions/${subscriptionId}/cancel`, {
  method: "POST",
  headers: {
    Authorization: process.env.MOOSYL_SECRET_KEY,
  },
});

Cancellation is scheduled for the end of the current billing period (pending_cancellation). The subscription remains active until then.

Look Up by External User

Retrieve a customer's active subscription using their external user ID:

const res = await fetch(
  `https://api.moosyl.com/subscriptions/by-external-user/${externalUserId}`,
  {
    headers: { Authorization: process.env.MOOSYL_SECRET_KEY },
  }
);

const { data: subscription } = await res.json();

Billing Cycle

When a subscription is active, Moosyl automatically:

  1. Generates an invoice at each billing date
  2. Creates a payment request for the invoice amount
  3. Advances nextBillingDate to the next interval
  4. If payment fails, the subscription moves to past_due
  5. When a payment completes, the subscription returns to active

You can monitor invoices, payment requests, and billing history from the subscription detail page in the dashboard.

Manage from Dashboard

The Moosyl dashboard provides full visibility under the Billing section:

  • Products — create and view products, add prices per interval
  • Customers — view customers and their subscriptions
  • Subscriptions — filter by status, view billing history and invoices

API Reference

All endpoints require a secret API key in the Authorization header.

MethodEndpointDescription
POST/productsCreate a product
GET/productsList products with prices
GET/products/:idGet product with prices
PATCH/products/:idUpdate a product
PATCH/products/:id/archiveArchive a product
POST/pricesCreate a price
GET/prices/:idGet a price
PATCH/prices/:idUpdate a price
PATCH/prices/:id/archiveArchive a price
POST/customersCreate a customer
GET/customersList customers
PATCH/customers/:idUpdate a customer
POST/subscriptionsCreate a subscription
GET/subscriptionsList subscriptions
GET/subscriptions/:idGet a subscription
POST/subscriptions/:id/cancelCancel a subscription
POST/subscriptions/by-external-userCreate by external user
GET/subscriptions/by-external-user/:idGet by external user

See the full interactive API reference at api.moosyl.com/docs.

Next Steps

Subscriptions | Moosyl Docs