Docs/Introduction
5-minute quickstart

Ship auth, plans, and payments without building any of it

Astapa gives you a complete backend for user authentication, subscription management, and local payment processing — all through a single API. Redirect users to our hosted login, read a signed JWT, and gate features by plan. That's it.

What you get

🔐

Hosted Authentication

Email/password, Google, and GitHub OAuth. We handle signup, login, email verification, and password resets.

📋

Plan Management

Create subscription tiers in the dashboard. Assign plans to users. The JWT carries the plan — your app just reads it.

💳

Local Payments

QRIS, GoPay, OVO, bank transfers via Xendit. Built for Southeast Asia from day one.

🤖

MCP Auth

JWT-based authentication for AI agents and MCP servers. client_credentials flow with scoped access.

How it works

Three steps. No auth infrastructure to build or maintain.

1

Create a project

Head to your dashboard and create a new project. You'll get a client_id and client_secret. Add your app's callback URL as a redirect URI.

2

Redirect to hosted login

Send your users to our hosted login page. They can sign up or sign in with email, Google, or GitHub. After authentication, we redirect them back to your app with an authorization code.

login.tstypescript
// Redirect user to Astapa's hosted login
const params = new URLSearchParams({
  client_id: process.env.ASTAPA_CLIENT_ID,
  redirect_uri: "https://yourapp.com/callback",
});

window.location.href = `https://astapa.com/auth/login?${params}`;
3

Exchange the code for tokens

Your callback handler receives the authorization code. Exchange it for an access token (JWT) and a refresh token. The JWT contains the user's identity, email, and any custom claims like their subscription plan.

callback.tstypescript
// Exchange authorization code for tokens
const res = await fetch("https://astapa.com/api/platform/token", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    grant_type: "authorization_code",
    code: searchParams.get("code"),
    client_id: process.env.ASTAPA_CLIENT_ID,
    client_secret: process.env.ASTAPA_CLIENT_SECRET,
    redirect_uri: "https://yourapp.com/callback",
  }),
});

const { access_token, refresh_token, expires_in } = await res.json();
// access_token is a signed JWT (RS256) — verify it with our JWKS endpoint

What's in the JWT

Every access token is a signed JWT. Decode it and you'll find everything you need to identify the user and gate features — no extra API calls required.

decoded-jwt.jsonjson
{
  "sub": "42",
  "email": "user@example.com",
  "email_verified": true,
  "project_id": "proj_abc123",
  "custom_claims": {
    "plan": "pro",
    "role": "admin",
    "feature_flags": ["beta_dashboard", "export_csv"]
  },
  "iss": "https://astapa.com",
  "aud": "your_client_id",
  "exp": 1712345678,
  "iat": 1712342078
}
Feature gating is just an if-statement
Read custom_claims.plan from the JWT and gate features in your app. No database queries, no extra API calls. When a user upgrades, set their new plan via the Claims API, refresh the token, and they're on the new plan instantly.

Token lifecycle

Access tokens expire after 1 hour. Use the refresh token to get a new one without re-authenticating. This is typically handled transparently in your middleware.

Refresh
Call POST /api/platform/token with grant_type=refresh_token. You get a fresh JWT with updated claims.
Instant plan upgrade
Set the new plan via Claims API, then immediately refresh the token. The user sees their new plan without waiting for the old JWT to expire.
Logout & revocation
Call POST /api/platform/revoke to invalidate all refresh tokens, then clear cookies. The user can't refresh anymore.

Base URL

All API endpoints are relative to your Astapa deployment. If you're using the hosted version:

https://astapa.com/api/platform/...
Self-hosted?
If you're running Astapa on your own infrastructure, replace astapa.com with your deployment's origin. All paths stay the same.

Sandbox mode

Every project starts in sandbox mode. Sandbox projects work exactly like production — same APIs, same JWTs, same flows — but with relaxed rate limits and test data isolation. When you're ready to go live, flip the toggle in your dashboard.

Sandbox limitations
Sandbox projects are limited to 10 end users and payment webhooks are simulated. Switch to production when you're ready to accept real payments.

Ready to build?

Pick where you want to go next.

API Playground
Click "Try it" on any endpoint to get started.
Getting Started | Astapa