Skip to content

Billing API Reference

This guide provides detailed information about the Billing API endpoints for managing subscriptions and plans.

Authentication

All billing endpoints require authentication using a User Authentication Token. Additionally, you must be the project owner to access billing information and manage subscriptions.

bash
Authorization: Bearer YOUR_USER_AUTHENTICATION_TOKEN

For more information about authentication, see the Authentication Guide.

Get Billing Information

Retrieve billing information for a project, including current plan, subscription status, and billing portal URL.

http
GET /api/v1/projects/:project_uuid/billing
Authorization: Bearer YOUR_USER_AUTHENTICATION_TOKEN

Example with curl:

bash
curl -X GET "https://app.uptinio.com/api/v1/projects/PRJ123456789/billing" \
  -H "Authorization: Bearer YOUR_USER_AUTHENTICATION_TOKEN" \
  -H "Content-Type: application/json"

Path Parameters

ParameterTypeDescription
project_uuidstringThe UUID of the project

Response

json
{
  "project": {
    "uuid": "PRJ123456789",
    "name": "My Team"
  },
  "current_plan": {
    "id": 1,
    "name": "Solo",
    "stripe_id": "prod_xxx",
    "currency": "usd",
    "decimal_price": 9.99,
    "description": "Perfect for individuals",
    "features": {
      "network_monitors_limit": 10,
      "status_pages_limit": 1,
      "team_members_limit": 1,
      "ai_analysis_limit_per_month": 10
    },
    "active": true,
    "created_at": "2024-01-01T00:00:00Z",
    "updated_at": "2024-01-01T00:00:00Z"
  },
  "active_subscription": {
    "id": 1,
    "name": "default",
    "status": "active",
    "processor": "stripe",
    "processor_id": "sub_xxx",
    "trial_ends_at": null,
    "ends_at": null,
    "created_at": "2024-01-01T00:00:00Z",
    "updated_at": "2024-01-01T00:00:00Z",
    "plan": {
      "id": 1,
      "name": "Solo",
      "stripe_id": "prod_xxx",
      "currency": "usd",
      "decimal_price": 9.99,
      "description": "Perfect for individuals",
      "features": {
        "network_monitors_limit": 10,
        "status_pages_limit": 1,
        "team_members_limit": 1,
        "ai_analysis_limit_per_month": 10
      },
      "active": true,
      "created_at": "2024-01-01T00:00:00Z",
      "updated_at": "2024-01-01T00:00:00Z"
    }
  },
  "billing_portal_url": "https://billing.stripe.com/p/session/xxx",
  "upcoming_invoice_amount": 9.99,
  "plan_price": 9.99
}

Response Fields

FieldTypeDescription
projectobjectProject information
current_planobjectCurrent plan details (see Plan object below)
active_subscriptionobject|nullActive subscription details (null if on free plan)
billing_portal_urlstring|nullURL to Stripe billing portal for managing payment methods and invoices
upcoming_invoice_amountnumber|nullAmount of the next invoice (if subscription exists)
plan_pricenumberCurrent plan price

Plan Object

FieldTypeDescription
idintegerPlan ID
namestringPlan name (e.g., "Free", "Solo", "Team", "Agency")
stripe_idstringStripe product ID
currencystringCurrency code (e.g., "usd")
decimal_pricenumberPlan price in decimal format (e.g., 9.99)
descriptionstringPlan description
featuresobjectPlan features and limits (JSON object)
activebooleanWhether the plan is active
created_atstringISO 8601 timestamp
updated_atstringISO 8601 timestamp

Subscription Object

FieldTypeDescription
idintegerSubscription ID
namestringSubscription name
statusstringSubscription status (e.g., "active", "canceled", "past_due")
processorstringPayment processor (e.g., "stripe")
processor_idstringProcessor subscription ID
trial_ends_atstring|nullISO 8601 timestamp when trial ends
ends_atstring|nullISO 8601 timestamp when subscription ends
planobject|nullAssociated plan object
created_atstringISO 8601 timestamp
updated_atstringISO 8601 timestamp

List Available Plans

Retrieve a list of all available subscription plans.

http
GET /api/v1/billing/plans
Authorization: Bearer YOUR_USER_AUTHENTICATION_TOKEN

Example with curl:

bash
curl -X GET "https://app.uptinio.com/api/v1/billing/plans" \
  -H "Authorization: Bearer YOUR_USER_AUTHENTICATION_TOKEN" \
  -H "Content-Type: application/json"

Response

json
[
  {
    "id": 1,
    "name": "Free",
    "stripe_id": "prod_free",
    "currency": "usd",
    "decimal_price": 0,
    "description": "Perfect for getting started",
    "features": {
      "network_monitors_limit": 3,
      "status_pages_limit": 1,
      "team_members_limit": 1,
      "ai_analysis_limit_per_month": 0
    },
    "active": true,
    "created_at": "2024-01-01T00:00:00Z",
    "updated_at": "2024-01-01T00:00:00Z"
  },
  {
    "id": 2,
    "name": "Solo",
    "stripe_id": "prod_solo",
    "currency": "usd",
    "decimal_price": 9.99,
    "description": "Perfect for individuals",
    "features": {
      "network_monitors_limit": 10,
      "status_pages_limit": 1,
      "team_members_limit": 1,
      "ai_analysis_limit_per_month": 10
    },
    "active": true,
    "created_at": "2024-01-01T00:00:00Z",
    "updated_at": "2024-01-01T00:00:00Z"
  }
]

Create Checkout Session

Create a Stripe checkout session for upgrading or subscribing to a plan. If the project already has an active subscription, it will be swapped to the new plan immediately.

http
POST /api/v1/projects/:project_uuid/billing/checkout
Authorization: Bearer YOUR_USER_AUTHENTICATION_TOKEN
Content-Type: application/json

Example with curl:

bash
curl -X POST "https://app.uptinio.com/api/v1/projects/PRJ123456789/billing/checkout" \
  -H "Authorization: Bearer YOUR_USER_AUTHENTICATION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "stripe_product_id": "prod_xxx",
    "success_url": "https://yourapp.com/billing/success",
    "cancel_url": "https://yourapp.com/billing/cancel"
  }'

Path Parameters

ParameterTypeDescription
project_uuidstringThe UUID of the project

Request Body

json
{
  "stripe_product_id": "prod_xxx",
  "success_url": "https://yourapp.com/billing/success",
  "cancel_url": "https://yourapp.com/billing/cancel"
}

Request Fields

FieldTypeRequiredDescription
stripe_product_idstringYesStripe product ID for the plan
success_urlstringNoURL to redirect after successful checkout (defaults to billing page)
cancel_urlstringNoURL to redirect if checkout is cancelled (defaults to billing page)

Response

New Subscription (200 OK) - Checkout session created:

json
{
  "checkout_url": "https://checkout.stripe.com/c/pay/xxx",
  "checkout_session_id": "cs_xxx"
}

Existing Subscription (200 OK) - Subscription swapped immediately:

json
{
  "message": "Subscription updated successfully",
  "subscription": {
    "id": 1,
    "name": "default",
    "status": "active",
    "processor": "stripe",
    "processor_id": "sub_xxx",
    "plan": {
      "id": 2,
      "name": "Team",
      "decimal_price": 29.99,
      ...
    },
    ...
  }
}

Error Responses:

400 Bad Request - Missing required field:

json
{
  "error": "stripe_product_id is required"
}

403 Forbidden - User is not the project owner:

json
{
  "error": "You must be the project owner to access billing"
}

422 Unprocessable Entity - Stripe error:

json
{
  "error": "Failed to retrieve product from Stripe",
  "details": "No such product: prod_invalid"
}

Downgrade Subscription

Downgrade an existing subscription to a different plan. This will swap the subscription immediately without proration.

http
POST /api/v1/projects/:project_uuid/billing/downgrade
Authorization: Bearer YOUR_USER_AUTHENTICATION_TOKEN
Content-Type: application/json

Example with curl:

bash
curl -X POST "https://app.uptinio.com/api/v1/projects/PRJ123456789/billing/downgrade" \
  -H "Authorization: Bearer YOUR_USER_AUTHENTICATION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "stripe_product_id": "prod_xxx"
  }'

Path Parameters

ParameterTypeDescription
project_uuidstringThe UUID of the project

Request Body

json
{
  "stripe_product_id": "prod_xxx"
}

Request Fields

FieldTypeRequiredDescription
stripe_product_idstringYesStripe product ID for the plan to downgrade to

Response

Success (200 OK):

json
{
  "message": "Subscription downgraded successfully",
  "subscription": {
    "id": 1,
    "name": "default",
    "status": "active",
    "processor": "stripe",
    "processor_id": "sub_xxx",
    "plan": {
      "id": 1,
      "name": "Solo",
      "decimal_price": 9.99,
      ...
    },
    ...
  }
}

Error Responses:

400 Bad Request - Missing required field:

json
{
  "error": "stripe_product_id is required"
}

403 Forbidden - User is not the project owner:

json
{
  "error": "You must be the project owner to access billing"
}

404 Not Found - No active subscription:

json
{
  "error": "No active subscription found"
}

422 Unprocessable Entity - Failed to downgrade:

json
{
  "error": "Failed to downgrade subscription",
  "details": "Error message from Stripe"
}

Billing Portal

The billing portal URL returned in the billing information allows users to:

  • Update payment methods
  • View and download invoices
  • Update billing information
  • Cancel subscriptions

The portal URL is generated by Stripe and is valid for a limited time. You should request a new billing information endpoint call to get a fresh portal URL when needed.

Error Responses

All endpoints may return the following error responses:

401 Unauthorized - Missing or invalid authentication token:

json
{
  "error": "Unauthorized"
}

403 Forbidden - User is not the project owner:

json
{
  "error": "You must be the project owner to access billing"
}

404 Not Found - Project not found:

json
{
  "error": "Project not found or you do not have access to it"
}

Notes

  • Only project owners can access billing endpoints
  • Upgrades use proration (always_invoice), so you'll be charged immediately for the difference
  • Downgrades don't use proration (none), so the change takes effect at the next billing cycle
  • The billing portal URL expires after a period of time - request a new one when needed
  • All prices are in the plan's currency (typically USD)
  • Plan features are stored as a JSON object and may vary by plan