Skip to content

Plans API

🤖 Explain with AI

Plans API is designed to manage subscription plans efficiently. It supports plan creation, listing all plans, retrieval by ID, modification, and deletion, allowing seamless management of memberships.

The API ensures clear and consistent responses, including detailed error handling, to provide a smooth experience for developers.

Create a plan

Endpoint

POST /v1/plans/

This endpoint allows creating a new recurring plan in the system by sending a POST request with the plan details — such as name, description, amount, currency, interval (frequency of charge), trial_period_days, and an optional image. If the operation is successful, it confirms the plan’s creation and provides its unique key.

Query Parameters:

Parameter Description Type Required
test Indicates if the plan is in test mode boolean false

Request Body Fields:

Parameter Description Type Required
name Plan name (max 50 characters) string true
description Plan description (max 300 characters) string false
currency Currency code (USD, EUR, CRC, etc.) string true
amount Plan price (decimal format) decimal true
interval Billing frequency (month, year) string true
interval_count Number of intervals between billings integer true
trial_period_days Trial period in days integer false
image Base64 encoded image or image URL string false

Request (cURL):

curl -X POST 'http://127.0.0.1:8000/v1/plans/?test=false' \
     -H 'Authorization: Api-Key sk_test_51O62xYzAbcDef123' \
     -H 'Content-Type: application/json' \
     -d '{
           "name": "Premium Plan",
           "description": "Unlimited access to all features",
           "currency": "USD",
           "amount": 9.99,
           "interval": "month",
           "interval_count": 1,
           "trial_period_days": 7,
           "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg..."
         }'

Request (Python):

import requests

api_key = "sk_test_51O62xYzAbcDef123"
response = requests.post(
    'http://127.0.0.1:8000/v1/plans/?test=false',
    headers={
        'Authorization': f'Api-Key {api_key}',
        'Content-Type': 'application/json'
    },
    json={
        "name": "Premium Plan",
        "description": "Unlimited access to all features",
        "currency": "USD",
        "amount": 9.99,
        "interval": "month",
        "interval_count": 1,
        "trial_period_days": 7
    }
)
print(response.json())

Request (Postman):

  1. Method: POST
  2. URL: http://127.0.0.1:8000/v1/plans/?test=false
  3. Authorization: Api-Key with value sk_test_51O62xYzAbcDef123
  4. Body (raw JSON):
{
    "name": "Premium Plan",
    "description": "Unlimited access to all features",
    "currency": "USD",
    "amount": 9.99,
    "interval": "month",
    "interval_count": 1,
    "trial_period_days": 7
}

Response (201 Created):

{
    "code": 201,
    "title": "Complete registration",
    "content": "The registration was successfully completed.",
    "type": "success",
    "data": {
        "id": "d36a4a5c-9fa9-4d55-b47f-4f1d50f2a180"
    }
}

Get all plans

Endpoint

GET /v1/plans/

This endpoint retrieves a paginated list of all plans with advanced filtering support.

Query Parameters:

Parameter Description Type Required
page Page number for pagination (default: 1) integer false
page_size Number of plans per page (default: 10, max: 100) integer false
test Filter by test mode (true/false) boolean false
name Search by plan name string false
price_min Minimum plan price decimal false
price_max Maximum plan price decimal false
interval Filter by billing interval (month, year) string false
interval_count Filter by interval count integer false
subscribers_min Minimum number of active subscribers integer false
subscribers_max Maximum number of active subscribers integer false
trial_days Filter by trial period days integer false
status Filter by status (active/inactive, true/false) string false

Request (List All Plans):

curl -X GET 'http://127.0.0.1:8000/v1/plans/?page=1&page_size=10&test=false' \
     -H 'Authorization: Api-Key sk_test_51O62xYzAbcDef123'

Request (With Filters):

curl -X GET 'http://127.0.0.1:8000/v1/plans/?page=1&name=premium&price_min=5&price_max=50&status=active' \
     -H 'Authorization: Api-Key sk_test_51O62xYzAbcDef123'

Response (200 OK):

{
  "count": 2,
  "current_page": 1,
  "total_pages": 1,
  "results": [
    {
      "key": "f1a2b3c4-5678-90ab-cdef-1234567890ab",
      "information": {
        "name": "Premium Plan",
        "created": "2025-08-17T20:00:00Z",
        "interval": "month",
        "interval_count": 1,
        "currency": "USD",
        "amount": "9.99",
        "trial_period_days": 7,
        "credit_card_description": "PREMIUM",
        "description": "Unlimited access to all features with premium support.",
        "email": "developer@example.com",
        "company_name": "Acme Corp",
        "page": "https://acme.com",
        "active": true,
        "count": 150,
        "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...",
        "image_dev": "https://acme.com/logo.png"
      },
      "test": false
    },
    {
      "key": "a1b2c3d4-5678-90ef-ghij-1234567890cd",
      "information": {
        "name": "Basic Plan",
        "created": "2025-08-17T20:05:00Z",
        "interval": "month",
        "interval_count": 1,
        "currency": "USD",
        "amount": "4.99",
        "trial_period_days": 0,
        "credit_card_description": "BASIC",
        "description": "Limited access to basic features with standard support.",
        "email": "developer@example.com",
        "company_name": "Acme Corp",
        "page": "https://acme.com",
        "active": true,
        "count": 45,
        "image": null,
        "image_dev": "https://acme.com/logo.png"
      },
      "test": false
    }
  ]
}

Get a specific plan

Endpoint

GET /v1/plans/{id}/

This endpoint retrieves complete details of a specific plan by its unique key.

Path Parameters:

Parameter Description Type Required
id The unique identifier of a plan (key) string true

Query Parameters:

Parameter Description Type Required
test Filter by test mode (true/false) boolean false

Request:

curl -X GET 'http://127.0.0.1:8000/v1/plans/f9b77185-a62e-4da9-a056-3c7b812ca334/' \
     -H 'Authorization: Api-Key sk_test_51O62xYzAbcDef123'

Response (200 OK):

{
  "key": "f9b77185-a62e-4da9-a056-3c7b812ca334",
  "information": {
    "name": "Standard Plan",
    "created": "2025-03-25T08:50:15.732299Z",
    "interval": "month",
    "interval_count": 1,
    "currency": "USD",
    "amount": "19.99",
    "trial_period_days": 0,
    "credit_card_description": "STANDARD",
    "description": "This plan offers access to standard features with basic support.",
    "email": "developer@example.com",
    "company_name": "Acme Corp",
    "page": "https://acme.com",
    "active": true,
    "count": 75,
    "image": null,
    "image_dev": "https://acme.com/logo.png"
  },
  "test": true
}

Response (404 Not Found):

{
  "code": 404,
  "title": "Plan does not exist",
  "content": "The requested plan does not exist, please verify.",
  "type": "danger"
}

Update a plan

Endpoint

PUT /v1/plans/{id}/

Updates an existing plan with new details. You can update individual fields including name, description, image, and trial period days without affecting others.

Path Parameters:

Parameter Description Type Required
id The unique identifier of a plan (key) string true

Query Parameters:

Parameter Description Type Required
test Filter by test mode (true/false) boolean false

Request Body Fields (all optional):

Parameter Description Type
name Plan name (max 50 characters) string
description Plan description (max 300 characters) string
image Base64 encoded image or image URL string
trial_period_days Trial period in days integer
is_test Indicates test or production environment boolean

Request:

curl -X PUT 'http://127.0.0.1:8000/v1/plans/f9b77185-a62e-4da9-a056-3c7b812ca334/' \
     -H 'Authorization: Api-Key sk_test_51O62xYzAbcDef123' \
     -H 'Content-Type: application/json' \
     -d '{
           "name": "Updated Premium Plan",
           "description": "Updated description with full access to features",
           "trial_period_days": 14,
           "is_test": false
         }'

Response (200 OK):

{
    "code": 200,
    "title": "Plan actualizado",
    "content": "El plan Updated Premium Plan fue actualizado correctamente.",
    "type": "success",
    "data": "f9b77185-a62e-4da9-a056-3c7b812ca334"
}

Response (404 Not Found):

{
    "code": 404,
    "title": "Plan no encontrado",
    "content": "El plan con ID f9b77185-a62e-4da9-a056-3c7b812ca334 no existe o no tienes permisos para modificarlo.",
    "type": "danger"
}

Response (200 - No Changes):

{
    "code": 200,
    "title": "Sin cambios",
    "content": "No se detectaron cambios en el plan.",
    "type": "info",
    "data": "f9b77185-a62e-4da9-a056-3c7b812ca334"
}

Delete a plan

Endpoint

DELETE /v1/plans/{id}/

Permanently deletes a plan and all associated subscriptions. When a plan is deleted, all customers with active subscriptions are notified via email.

Path Parameters:

Parameter Description Type Required
id The unique identifier of a plan (key) string true

Request:

curl -X DELETE 'http://127.0.0.1:8000/v1/plans/f9b77185-a62e-4da9-a056-3c7b812ca334/' \
     -H 'Authorization: Api-Key sk_test_51O62xYzAbcDef123'

Response (200 OK):

{
    "code": 200,
    "title": "Plan deleted",
    "content": "The plan f9b77185-a62e-4da9-a056-3c7b812ca334 was deleted successfully.",
    "type": "success"
}

Response (404 Not Found):

{
    "code": 404,
    "title": "Plan does not exist",
    "content": "The plan f9b77185-a62e-4da9-a056-3c7b812ca334 does not exist or has already been deleted.",
    "type": "danger"
}

Error Handling

The API returns standard HTTP status codes to indicate the success or failure of a request. Below are common errors specific to plans:

400 Bad Request

Occurs when the request is malformed or has invalid data.

Scenarios:

Scenario Error Message Solution
Invalid price range "El precio mínimo no puede ser mayor que el máximo." Ensure price_min ≤ price_max
Invalid subscriber range "El mínimo de suscriptores no puede ser mayor que el máximo." Ensure subscribers_min ≤ subscribers_max
Plan not found "El plan consultado no existe." Verify the plan key or filters

Example Error Response:

{
    "code": 400,
    "title": "Rango de precios inválido",
    "content": "El precio mínimo no puede ser mayor que el máximo.",
    "type": "warning"
}

401 Unauthorized

Authentication failed. API Key is invalid, missing, or malformed.

Example:

{
    "detail": "Authentication credentials were not provided."
}

Solution:

  • Verify you included the Authorization: Api-Key sk_test_... header
  • Ensure your API Key is correct and active
  • Test with Postman using the Api-Key authentication method

404 Not Found

The requested plan does not exist.

Example:

{
    "code": 404,
    "title": "Plan does not exist",
    "content": "The requested plan does not exist, please verify.",
    "type": "danger"
}

Solution:

  • Verify the plan key exists
  • Use the list endpoint to find the correct plan key
  • Ensure the plan belongs to your developer account

Important Notes

Plan Deletion

  • Deleting a plan will cancel all active subscriptions
  • Customers will be notified via email about the plan deletion
  • This action cannot be undone

Test vs Production

  • Use your Test Key (sk_test_...) for development and testing
  • Use your Live Key (sk_live_...) for real transactions
  • Query parameter ?test=true or ?test=false controls the mode
  • The system automatically detects the mode based on the API Key used

Intervals

  • month - Monthly billing
  • year - Yearly billing
  • interval_count specifies how many intervals (e.g., interval=month, interval_count=3 = every 3 months)

Trial Period

  • Trial period is specified in days
  • Set trial_period_days to 0 for no trial
  • During trial period, customers are not charged
  • After trial expires, first charge is applied

Filtering

  • Multiple filters can be combined
  • Filters are applied with AND logic
  • Search parameters use case-insensitive matching

Best Practices

  1. Clear plan names - Use descriptive names that clearly indicate the tier and features
  2. Accurate descriptions - Provide detailed descriptions of what’s included in each plan
  3. Appropriate pricing - Ensure prices are competitive and reflect the value provided
  4. Trial periods - Consider offering trial periods to reduce customer acquisition friction
  5. Test before production - Use test mode with test API keys for validation
  6. Monitor subscribers - Use the subscriber count in responses to track plan adoption
  7. Plan versioning - Create new plans instead of heavily modifying existing ones with subscribers
  8. Image optimization - Use optimized images to reduce API response times

Troubleshooting

Problem: “Plan does not exist”

Cause: Plan key doesn’t exist or belongs to a different developer account
Solution: - Verify the plan key using the list endpoint - Ensure you’re using the correct API Key - Check that the plan hasn’t been deleted

Problem: “Authentication credentials were not provided”

Cause: Missing or invalid API Key authentication
Solution: - Use Authorization: Api-Key sk_test_... header in your request - Verify your API Key is active - Test with Postman using the Api-Key authentication

Problem: “El precio mínimo no puede ser mayor que el máximo”

Cause: Invalid price range filter provided
Solution: - Ensure price_minprice_max - Check the filter values are valid numbers

Problem: “El plan consultado no existe”

Cause: Query filters didn’t match any plans
Solution: - Verify filter parameters are correct - Try listing all plans without filters - Check if the plan exists in test mode (adjust test parameter)


FAQ

Q: Can I change the price of an existing plan?
A: No, plan pricing is immutable. Create a new plan with the updated price and migrate customers to it.

Q: What happens when I delete a plan?
A: All active subscriptions are cancelled and customers are notified. This action cannot be undone.

Q: Can I have multiple plans with the same name?
A: Yes, but it’s recommended to use unique names for easier management and identification.

Q: How many plans can I create?
A: There is no limit on the number of plans you can create.

Q: Can I update interval or interval_count after creation?
A: No, these are immutable. Create a new plan with the desired billing frequency.

Q: What’s the difference between interval and interval_count?
A: interval is the unit (month, year), and interval_count is the multiplier (e.g., every 3 months = interval=month, interval_count=3).

Q: Can I use the same plan for multiple products?
A: Yes, plans are independent of products. A plan represents a billing cycle configuration.

Q: How do I check the number of active subscribers for a plan?
A: Use the list or get endpoints. The information.count field shows active subscriptions.