@mesub/node wraps this API. Use it directly from any other language.12curl "https://api.mesub.io/v1/project" \ -H "Authorization: Bearer $MESUB_API_KEY"
https://api.mesub.io/v1 and takes the project's
API key as a bearer token. The key identifies the project: there is no
project id in any path. Authentication has the detail."9990000" is
9.99 of a token with six decimals./v1/subscriptions, /v1/access and
/v1/events. The other routes ignore one.code to branch on./v1 is versioned by date. Name the version you wrote your
code against in the Mesub-Version header:123curl "https://api.mesub.io/v1/project" \ -H "Authorization: Bearer $MESUB_API_KEY" \ -H "Mesub-Version: 2026-10-02"
2026-10-02 is the only version served today, and no answer depends on the
version yet. @mesub/node sends the header on every call.| You send | Mesub answers |
| A version Mesub serves | As that version |
| No header | As the first version, 2026-10-02 |
| Anything else, an empty header too | 400 unsupported_version |
unsupported_version lists the versions served. The API key
is checked first: a missing or wrong key answers 401 whatever the header says.Mesub-Version header.fb782da, of 2026-10-20.| Route | What it answers | SDK |
GET /v1/access | Whether a customer has access to a plan | hasAccess, access |
GET /v1/access | Without plan: every plan the customer has anything on | accessList |
GET /v1/project | The id of the project the key belongs to |
| Route | What it answers | SDK |
GET /v1/plans | Every published plan of the project that has a slug, sorted | plans.list |
GET /v1/plans/:slug | One plan: name, price, period, token, status, end date | plans.retrieve |
| Route | What it does | subscriptions. |
POST /v1/subscriptions | Reserves one, builds what is signed | create |
POST /v1/subscriptions/:id/transaction | Builds a fresh transaction to sign | transaction |
POST /v1/subscriptions/:id/submit | Sends what the wallet signed | submit |
GET /v1/subscriptions | A customer's subscriptions, paginated | list |
GET /v1/subscriptions/:id | One subscription | retrieve |
GET /v1/subscriptions/:id/attempts | Its charges, with the total paid | attempts |
POST /v1/subscriptions/:id/retry | Charges a late payment now | retry |
POST /v1/subscriptions/:id/cancel | Builds the cancellation | cancel |
POST /v1/subscriptions/:id/cancel/confirm | Confirms it | confirmCancel |
POST /v1/subscriptions/:id/resume | Builds the undo of a cancellation | resume |
POST /v1/subscriptions/:id/resume/confirm | Confirms it | confirmResume |
POST /v1/subscriptions/:id/close | Builds the closing of an ended one | close |
POST /v1/subscriptions/:id/close/confirm | Confirms it | confirmClose |
| Route | What it answers | SDK |
GET /v1/events | The webhook events of the last 30 days, newest first | events.list |
GET /v1/events/:id | One event | events.retrieve |
limit (1 to 100, 20 by default, 25 on events) and
starting_after, the id of the last item of the previous page, and answer
{ data, has_more }. Items come newest first. Attempts add paid, and events
add available_since.GET /v1/plans answers { plans }, every plan
at once, and GET /v1/access without plan answers
{ plans, revalidate_after }.GET /v1/subscriptions lists one customer's subscriptions, named by wallet,
external_id or email. No route lists every subscription of the project:
that list is in the dashboard and
the MCP server.12345curl -G "https://api.mesub.io/v1/subscriptions" \ -H "Authorization: Bearer $MESUB_API_KEY" \ -d external_id=user_42 \ -d limit=50 \ -d starting_after=cmg1x0abc0001
subscriptions.listAll and subscriptions.allAttempts walk
every page for you.