Eshway Subscriptions API
The Subscriptions API from Eshway — 10 operation(s) for subscriptions.
The Subscriptions API from Eshway — 10 operation(s) for subscriptions.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/eshway-com:eshway-com-subscriptions-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Fast Subscriptions API
version: 0.1.0
tags:
- name: Subscriptions
paths:
/v1/subscriptions/plans:
get:
tags:
- Subscriptions
summary: Get Plans
operationId: get_plans_v1_subscriptions_plans_get
responses:
'200':
description: Successful Response
content:
application/json:
schema:
items:
$ref: '#/components/schemas/SubscriptionPlanSchema'
type: array
title: Response Get Plans V1 Subscriptions Plans Get
/v1/subscriptions/my-subscriptions:
get:
tags:
- Subscriptions
summary: Get My Subscription
description: 'The current subscription of every org the caller actively belongs to.
Org-scoped, not purchase-scoped. This used to filter on
``admin_id == current_user.id`` — "subscriptions I personally bought" —
which showed an org admin "No active subscription found" whenever a
different admin had done the purchasing (2026-08-17, Adzzat). Any
active member can already read the same billing fields for their org
via GET /{orgId}/my-subscription, so listing them here exposes
nothing new. Mutating endpoints keep their own admin guards.
Membership is decided by is_still_member (a Python property over the
membership_periods JSON), so filter in Python, not SQL. Each org''s
row comes from _get_latest_org_subscription — the same resolver the
entitlement policy uses — so the plan this page shows and the plan
the backend enforces cannot disagree; it also owns the
PENDING-checkout exclusion.'
operationId: get_my_subscription_v1_subscriptions_my_subscriptions_get
responses:
'200':
description: Successful Response
content:
application/json:
schema:
items:
$ref: '#/components/schemas/OrgSubscriptionSchema'
type: array
title: Response Get My Subscription V1 Subscriptions My Subscriptions Get
security:
- OAuth2PasswordBearer: []
/v1/subscriptions/{orgId}/my-subscription:
get:
tags:
- Subscriptions
summary: Get Org Subscription
description: 'Read the current subscription for an organization.
Access: caller must be an active member of orgId. Billing details
(price, trial_end, members_cap) are organization-scoped — leaving
this endpoint unauthenticated would let anyone enumerate paying
customers and their plans by orgId.
This endpoint no longer performs the trial self-heal write that the
previous implementation did during a public GET. Performing writes
on a read path is wrong on multiple axes: it makes the endpoint
non-cacheable, it can race when the dashboard polls, and (when the
endpoint was unauthenticated) it let arbitrary callers trigger
state changes. Self-healing of trial price / trial_end is now
handled in the dedicated background subscription task — see
``app/tasks/subscription_tasks.py``.'
operationId: get_org_subscription_v1_subscriptions__orgId__my_subscription_get
security:
- OAuth2PasswordBearer: []
parameters:
- name: orgId
in: path
required: true
schema:
type: integer
title: Orgid
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/OrgSubscriptionSchema'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/v1/subscriptions/{orgId}/subscribe:
post:
tags:
- Subscriptions
summary: Create Subscription
operationId: create_subscription_v1_subscriptions__orgId__subscribe_post
security:
- OAuth2PasswordBearer: []
parameters:
- name: orgId
in: path
required: true
schema:
type: integer
title: Orgid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateSubscriptionRequest'
responses:
'200':
description: Successful Response
content:
application/json:
schema:
type: object
title: Response Create Subscription V1 Subscriptions Orgid Subscribe Post
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/v1/subscriptions/cancel:
post:
tags:
- Subscriptions
summary: Cancel Subscription
description: 'Cancel a subscription.
Authority is checked in two passes:
1. Locate the subscription by razorpay_subscription_id only —
we do NOT key on admin_id here, because using a stale
admin_id row to gate the action lets a former billing
admin keep cancelling the org''s subscription long after
they''ve been removed from the org.
2. Require the caller to be an active org admin of the
subscription''s CURRENT org.'
operationId: cancel_subscription_v1_subscriptions_cancel_post
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CancelSubscriptionRequest'
required: true
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
security:
- OAuth2PasswordBearer: []
/v1/subscriptions/{orgId}/verify-payment:
post:
tags:
- Subscriptions
summary: Verify Payment
operationId: verify_payment_v1_subscriptions__orgId__verify_payment_post
security:
- OAuth2PasswordBearer: []
parameters:
- name: orgId
in: path
required: true
schema:
type: integer
title: Orgid
requestBody:
required: true
content:
application/json:
schema:
type: object
title: Payment Details
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/v1/subscriptions/{orgId}/upgrade-seat:
post:
tags:
- Subscriptions
summary: Upgradeseat
description: 'Create a Razorpay order for a seat upgrade.
Authority is now bound to active org admin status, not the
historical admin_id on the subscription row. A removed billing
admin cannot drive seat upgrades for an org they no longer
belong to. The Razorpay order notes also bind back to the
requested orgId, expected admin id, currency, and amount so
/verify-seat-upgrade-payment can detect mismatches.'
operationId: upgradeSeat_v1_subscriptions__orgId__upgrade_seat_post
security:
- OAuth2PasswordBearer: []
parameters:
- name: orgId
in: path
required: true
schema:
type: integer
title: Orgid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpgradeSeatSubscriptionRequest'
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/v1/subscriptions/{orgId}/verify-seat-upgrade-payment:
post:
tags:
- Subscriptions
summary: Verify Seat Upgrade
operationId: verify_seat_upgrade_v1_subscriptions__orgId__verify_seat_upgrade_payment_post
security:
- OAuth2PasswordBearer: []
parameters:
- name: orgId
in: path
required: true
schema:
type: integer
title: Orgid
requestBody:
required: true
content:
application/json:
schema:
type: object
title: Payment Details
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/v1/subscriptions/debug-payment:
post:
tags:
- Subscriptions
summary: Debug Payment
description: 'Debug endpoint — platform superadmin only.
Previously gated only by ``settings.DEBUG``. If a misconfigured staging
or production env had ``DEBUG=True``, anyone could probe Razorpay
payment/subscription metadata. Now requires both: superadmin auth at
all times, plus the explicit DEBUG flag (so it cannot be invoked even
by a superadmin in a production environment).'
operationId: debug_payment_v1_subscriptions_debug_payment_post
requestBody:
content:
application/json:
schema:
type: object
title: Payment Details
required: true
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
security:
- OAuth2PasswordBearer: []
/v1/subscriptions/test-razorpay-config:
get:
tags:
- Subscriptions
summary: Test Razorpay Config
description: 'Test endpoint to verify Razorpay configuration.
Requires platform superadmin AND ``settings.DEBUG``. The previous
implementation gated only on ``DEBUG``, so a misconfigured
staging/production deploy with ``DEBUG=True`` would have let any
unauthenticated caller make outbound Razorpay API calls and
receive both whether live keys are configured AND raw provider
error text.'
operationId: test_razorpay_config_v1_subscriptions_test_razorpay_config_get
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
security:
- OAuth2PasswordBearer: []
components:
schemas:
PlanFeature:
properties:
name:
type: string
title: Name
included:
type: boolean
title: Included
description:
anyOf:
- type: string
- type: 'null'
title: Description
value:
anyOf:
- type: string
- type: integer
- type: 'null'
title: Value
type: object
required:
- name
- included
title: PlanFeature
OrgSubscriptionSchema:
properties:
id:
type: integer
title: Id
plan:
$ref: '#/components/schemas/SubscriptionPlanSchema'
org_id:
type: integer
title: Org Id
admin_id:
type: integer
title: Admin Id
razorpay_subscription_id:
anyOf:
- type: string
- type: 'null'
title: Razorpay Subscription Id
status:
type: string
title: Status
current_period_start:
type: string
format: date-time
title: Current Period Start
current_period_end:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Current Period End
grace_period_end:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Grace Period End
trial_end:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Trial End
cancel_at_period_end:
anyOf:
- type: boolean
- type: 'null'
title: Cancel At Period End
days_until_expiration:
anyOf:
- type: integer
- type: 'null'
title: Days Until Expiration
is_active:
type: boolean
title: Is Active
members_cap:
type: integer
title: Members Cap
monthly_bill:
type: number
title: Monthly Bill
currency:
type: string
title: Currency
type: object
required:
- id
- plan
- org_id
- admin_id
- status
- current_period_start
- current_period_end
- trial_end
- cancel_at_period_end
- days_until_expiration
- is_active
- members_cap
- monthly_bill
- currency
title: OrgSubscriptionSchema
UpgradeSeatSubscriptionRequest:
properties:
additional_seats:
type: integer
title: Additional Seats
type: object
required:
- additional_seats
title: UpgradeSeatSubscriptionRequest
CreateSubscriptionRequest:
properties:
plan_id:
type: string
title: Plan Id
plan_duration:
type: integer
title: Plan Duration
members_cap:
type: integer
title: Members Cap
type: object
required:
- plan_id
- plan_duration
- members_cap
title: CreateSubscriptionRequest
HTTPValidationError:
properties:
detail:
items:
$ref: '#/components/schemas/ValidationError'
type: array
title: Detail
type: object
title: HTTPValidationError
SubscriptionPlanSchema:
properties:
id:
type: string
title: Id
name:
type: string
title: Name
price:
type: integer
title: Price
interval:
type: string
title: Interval
description:
anyOf:
- type: string
- type: 'null'
title: Description
duration:
type: integer
title: Duration
features:
items:
$ref: '#/components/schemas/PlanFeature'
type: array
title: Features
popular:
anyOf:
- type: boolean
- type: 'null'
title: Popular
default: false
limitations:
anyOf:
- items:
type: string
type: array
- type: 'null'
title: Limitations
default: []
type: object
required:
- id
- name
- price
- interval
- description
- duration
- features
title: SubscriptionPlanSchema
ValidationError:
properties:
loc:
items:
anyOf:
- type: string
- type: integer
type: array
title: Location
msg:
type: string
title: Message
type:
type: string
title: Error Type
type: object
required:
- loc
- msg
- type
title: ValidationError
CancelSubscriptionRequest:
properties:
subscription_id:
type: string
title: Subscription Id
type: object
required:
- subscription_id
title: CancelSubscriptionRequest
securitySchemes:
OAuth2PasswordBearer:
type: oauth2
flows:
password:
scopes: {}
tokenUrl: token