Reference

API Reference

Complete reference for all API routes including authentication, users, payments, subscriptions, waitlist, and admin endpoints.

All API routes live under /api/. They return a consistent JSON response format:

Success:

json
{
  "success": true,
  "payload": { ... },
  "message": "Optional message"
}

Error:

json
{
  "success": false,
  "error": "Error description",
  "code": "OPTIONAL_ERROR_CODE"
}

Authentication

Send Magic Link

text
POST /api/auth/magic-link/send

Sends a magic link email to the user. Works for both new and existing users.

Body:

json
{
  "email": "user@example.com",
  "callbackUrl": "/dashboard"  // optional, where to redirect after login
}

Access: Public


Verify Invite Token

text
GET /api/auth/verify-invite?token=abc123

Checks if an invite token is valid (not expired, not used, not revoked).

Response:

json
{
  "success": true,
  "payload": {
    "email": "invited@example.com",
    "expiresAt": "2025-01-20T00:00:00Z"
  }
}

Access: Public


Sign Up With Invite

text
POST /api/auth/signup-with-invite

Creates a user account using a valid invite token.

Body:

json
{
  "token": "invite-token-here"
}

Access: Public


User Profile

Get Profile

text
GET /api/profile

Returns the currently authenticated user's profile.

Response:

json
{
  "success": true,
  "payload": {
    "id": "user-id",
    "name": "John Doe",
    "email": "john@example.com",
    "image": "https://...",
    "roles": ["USER"],
    "isActive": true,
    "planId": "product-id-or-null",
    "createdAt": "2025-01-01T00:00:00Z"
  }
}

Access: Authenticated


Update Profile

text
PUT /api/profile

Updates the current user's profile information.

Body:

json
{
  "name": "New Name"
}

Access: Authenticated


Payments

Create Checkout Session

text
POST /api/payment/checkout

Creates a checkout session with the configured payment provider. Redirects the user to the provider's hosted checkout page.

Body:

json
{
  "productId": "your-product-id",
  "billingPeriod": "monthly"  // "monthly" or "yearly" (subscription model only)
}

Response:

json
{
  "success": true,
  "payload": {
    "sessionId": "session-id",
    "checkoutUrl": "https://checkout.provider.com/...",
    "provider": "STRIPE"
  }
}

Access: Authenticated

Notes:

  • For one-time payment model, billingPeriod is ignored
  • Returns 409 if user already has an active subscription (subscription model)

Get Payment History

text
GET /api/payment/history

Returns all payments for the current user.

Response:

json
{
  "success": true,
  "payload": [
    {
      "id": "payment-id",
      "provider": "STRIPE",
      "status": "COMPLETED",
      "amount": 149,
      "currency": "USD",
      "planId": "product-id",
      "createdAt": "2025-01-15T00:00:00Z"
    }
  ]
}

Access: Authenticated


Payment Webhooks

text
POST /api/payment/webhook/stripe
POST /api/payment/webhook/dodo
POST /api/payment/webhook/polar

Receives webhook events from the payment provider. Only one of these exists in your variant.

Access: Public (verified by webhook signature)

Notes:

  • Do not call these manually. They are called by your payment provider.
  • The webhook secret in your env vars must match the one configured in the provider dashboard.

Subscriptions

Get Active Subscription

text
GET /api/subscription

Returns the current user's active subscription, or null if they do not have one.

Response:

json
{
  "success": true,
  "payload": {
    "id": "sub-id",
    "provider": "STRIPE",
    "status": "ACTIVE",
    "planId": "product-id",
    "currentPeriodStart": "2025-01-01T00:00:00Z",
    "currentPeriodEnd": "2025-02-01T00:00:00Z",
    "cancelAt": null
  }
}

Access: Authenticated


Get Billing Portal URL

text
GET /api/subscription/billing-portal?returnUrl=/payments

Returns a URL to the payment provider's customer portal where users can manage their subscription.

Query params:

  • returnUrl - Where to redirect after the user is done (required)

Response:

json
{
  "success": true,
  "payload": {
    "url": "https://billing.provider.com/portal/..."
  }
}

Access: Authenticated (must have an active subscription)


Waiting List

Join Waitlist

text
POST /api/waiting-list

Adds an email to the waitlist. Only works when platform mode is WAITLIST_WITH_INVITES.

Body:

json
{
  "email": "user@example.com"
}

Access: Public

Notes:

  • Returns 409 if email is already on the waitlist
  • Sends a welcome email automatically

Send Emails to Waitlist (Admin)

text
POST /api/waiting-list/send-emails

Sends launch or reminder emails to selected waitlist entries.

Body:

json
{
  "emails": ["user1@example.com", "user2@example.com"],
  "type": "launch"  // "launch" or "reminder"
}

Response:

json
{
  "success": true,
  "payload": {
    "sent": 5,
    "failed": 1
  }
}

Access: Admin only


Contact

Submit Contact Form

text
POST /api/contact

Sends a contact form notification email to the admin.

Body:

json
{
  "name": "John Doe",
  "email": "john@example.com",
  "message": "I have a question about..."
}

Access: Public


Admin Endpoints

List All Users

text
GET /api/users

Returns all registered users.

Access: Admin only


Toggle User Status

text
POST /api/users/:userId/toggle-status

Enables or disables a user account. Cannot disable admin users.

Access: Admin only


Start Impersonation

text
POST /api/admin/impersonate

Start impersonating a user. Sets a signed cookie.

Body:

json
{
  "targetUserId": "user-id-to-impersonate"
}

Access: Admin only


Get Impersonation Status

text
GET /api/admin/impersonate

Check if currently impersonating someone.

Access: Authenticated


Stop Impersonation

text
DELETE /api/admin/impersonate

Stop impersonating and return to admin view.

Access: Authenticated


List Waitlist Entries (Admin)

text
GET /api/admin/waiting-list

Returns all waitlist entries with their status.

Access: Admin only


List Invites

text
GET /api/admin/invites

Returns all invite records.

Access: Admin only


Create Invite

text
POST /api/admin/invites

Creates a new invite and sends the invitation email.

Body:

json
{
  "email": "newuser@example.com",
  "expiresInDays": 7
}

Access: Admin only

Notes:

  • Returns 409 if user already exists or invite already active

Delete Invite

text
DELETE /api/admin/invites/:email

Permanently deletes an invite record.

Access: Admin only


Revoke Invite

text
POST /api/admin/invites/:email/revoke

Marks an invite as revoked (keeps the record but makes it unusable).

Access: Admin only


Error Codes

Common error responses you may encounter:

StatusMeaning
400Bad request (validation failed or invalid input)
401Not authenticated (no valid session)
403Forbidden (insufficient role or account disabled)
404Resource not found
409Conflict (duplicate resource)
500Internal server error

Some errors include a code field for programmatic handling:

json
{
  "error": "You already have an active subscription",
  "code": "ACTIVE_SUBSCRIPTION_EXISTS"
}

Making API Calls from the Frontend

MoveFast uses an axios client pre-configured with the base URL. Import it and use the API_ROUTES constants:

typescript
import { axiosClient } from "@/lib/axios";
import { API_ROUTES } from "@/lib/api-routes";
 
// Example: fetch payment history
const response = await axiosClient.get(API_ROUTES.PAYMENT.HISTORY);
const payments = response.data.payload;
 
// Example: create checkout
const response = await axiosClient.post(API_ROUTES.PAYMENT.CHECKOUT, {
    productId: "your-product-id",
});
const { checkoutUrl } = response.data.payload;
window.location.href = checkoutUrl;

The axios client automatically includes cookies for authentication and handles the /api prefix.