NodeRailsCRYPTO PAYMENT INFRASTRUCTURE
DocumentationAPI Reference
Dashboard

Product Plans

Product plans define what you sell, both one-time purchases and recurring subscriptions. Each plan can have multiple price options with different billing intervals.


Create a product plan

POST/product-plans

Request body

ParameterTypeRequiredDescription
appIdstringYesYour app UUID
namestringYesPlan name (1–255 chars)
pricesPrice[]YesPrice options (min 1)
descriptionstringNoPlan description (max 2000)
imageUrlstringNoProduct image URL
planType"ONE_TIME" | "SUBSCRIPTION"NoPlan type
taxRateIdstringNoDefault tax rate
metadataobjectNoArbitrary key-value metadata

Price

FieldTypeRequiredDescription
amountstringYesPrice amount (decimal string)
currencystringNoCurrency code (max 10, default: USD)
billingIntervalstringNoMINUTE | DAY | WEEK | MONTH | YEAR
billingIntervalCountnumberNoInterval multiplier (e.g. 3 for quarterly)
trialPeriodDaysnumberNoFree trial length in days
nicknamestringNoPrice label (max 100, e.g. "Monthly")
sortOrdernumberNoDisplay ordering
isDefaultbooleanNoDefault price selection
metadataobjectNoPrice-level metadata
SDK exampletypescript
const plan = await noderails.productPlans.create({
  name: 'Pro Plan',
  description: 'Full access to all features',
  planType: 'SUBSCRIPTION',
  prices: [
    {
      amount: '9.99',
      currency: 'USD',
      billingInterval: 'MONTH',
      billingIntervalCount: 1,
      nickname: 'Monthly',
      isDefault: true,
    },
    {
      amount: '99.99',
      currency: 'USD',
      billingInterval: 'YEAR',
      billingIntervalCount: 1,
      nickname: 'Annual (save 17%)',
    },
  ],
});

console.log(plan.id);     // "plan_abc123"
console.log(plan.prices); // Price[]

List product plans

GET/product-plans

Query parameters

ParameterTypeDescription
appIdstringFilter by app UUID
planType"ONE_TIME" | "SUBSCRIPTION"Filter by plan type
pagenumberPage number (default: 1)
pageSizenumberItems per page (max 100)
SDK exampletypescript
const result = await noderails.productPlans.list({
  planType: 'SUBSCRIPTION',
  page: 1,
});

for (const plan of result.data) {
  console.log(plan.name, plan.prices.length);
}

Retrieve a product plan

GET/product-plans/:id
SDK exampletypescript
const plan = await noderails.productPlans.retrieve('plan_abc123');
console.log(plan.name);   // "Pro Plan"
console.log(plan.prices); // [{ amount: "9.99", ... }, { amount: "99.99", ... }]

Update a product plan

PUT/product-plans/:id
SDK exampletypescript
const updated = await noderails.productPlans.update('plan_abc123', {
  name: 'Pro Plan (v2)',
  description: 'Updated description',
  isActive: true,
});

Add a price

POST/product-plans/:id/prices

Adds a new price option to an existing product plan.

SDK exampletypescript
const price = await noderails.productPlans.addPrice('plan_abc123', {
  amount: '49.99',
  currency: 'USD',
  billingInterval: 'MONTH',
  billingIntervalCount: 6,
  nickname: 'Semi-Annual',
});

Update a price

PUT/product-plans/:planId/prices/:priceId
ParameterTypeRequiredDescription
amountstringNoUpdated price amount
nicknamestringNoUpdated label
sortOrdernumberNoDisplay order
isDefaultbooleanNoSet as default
isActivebooleanNoActive/inactive
trialPeriodDaysnumberNoTrial days

Deactivate a price

DELETE/product-plans/:planId/prices/:priceId

Deactivates a price option (soft delete). Returns { deactivated: true }.

SDK exampletypescript
await noderails.productPlans.deactivatePrice('plan_abc123', 'price_xyz');

Response object

All responses are wrapped in { "success": true, "data": ... }. List endpoints add pagination.

ProductPlan object (create / update / list)json
{
  "success": true,
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "appId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
    "name": "Pro Plan",
    "description": "Full access to all features",
    "imageUrl": null,
    "planType": "SUBSCRIPTION",
    "taxRateId": null,
    "isActive": true,
    "metadata": {},
    "createdAt": "2025-01-15T10:30:00.000Z",
    "updatedAt": "2025-01-15T10:30:00.000Z",
    "prices": [
      {
        "id": "c3d4e5f6-a7b8-9012-cdef-345678901234",
        "productPlanId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "appId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
        "amount": "9.99",
        "currency": "USD",
        "billingInterval": "MONTH",
        "billingIntervalCount": 1,
        "trialPeriodDays": 0,
        "nickname": "Monthly",
        "sortOrder": 0,
        "isDefault": true,
        "isActive": true,
        "metadata": {},
        "createdAt": "2025-01-15T10:30:00.000Z",
        "updatedAt": "2025-01-15T10:30:00.000Z"
      }
    ],
    "taxRate": null
  }
}

ProductPlan fields

idstringUnique plan UUID
appIdstringApp this plan belongs to
namestringPlan display name
descriptionstring | nullPlan description
imageUrlstring | nullProduct image URL
planTypestringONE_TIME or SUBSCRIPTION
taxRateIdstring | nullDefault tax rate UUID
isActivebooleanWhether the plan is active
metadataobjectArbitrary key-value pairs
createdAtstringISO 8601 creation timestamp
updatedAtstringISO 8601 last-update timestamp
pricesProductPlanPrice[]Price options, sorted by sortOrder ascending
taxRateTaxRate | nullFull tax rate object when linked

ProductPlanPrice fields

idstringPrice UUID
productPlanIdstringParent plan UUID
appIdstringApp UUID
amountstringPrice amount as decimal string
currencystringCurrency code
billingIntervalstring | nullMINUTE, DAY, WEEK, MONTH, or YEAR
billingIntervalCountnumber | nullInterval multiplier (e.g. 3 for quarterly)
trialPeriodDaysnumberFree trial length in days
nicknamestring | nullPrice label (e.g. 'Monthly')
sortOrdernumberDisplay ordering (ascending)
isDefaultbooleanWhether this is the default price
isActivebooleanWhether the price is active
metadataobjectPrice-level metadata
createdAtstringISO 8601 creation timestamp
updatedAtstringISO 8601 last-update timestamp
💡

Endpoint variations

Retrieve additionally includes the app object. Add price / update price return bare ProductPlanPrice scalars (no relations). Deactivate price returns { "deactivated": true }.