Skip to main content

API Reference

Complete reference for the Paycheck HTTP API.

Authentication

Public Endpoints

No authentication required. Called by end-user applications.

Admin Endpoints

Use Bearer token authentication:

Authorization: Bearer pc_xxxxxxxxxxxx

API keys are created via the operator or org member API.

Public Endpoints

POST /buy

Initiate a payment session.

Request:

{
"product_id": "prod_xxxxx"
}

Response: Redirects to Stripe/LemonSqueezy checkout.


GET /callback

Post-payment redirect. Returns activation code.

Query Parameters:

  • session_id - Stripe session ID, or
  • order_id - LemonSqueezy order ID

Response: Redirects to project's redirect_url with:

  • code - Activation code
  • project_id - Project ID
  • status - "success" or "error"

POST /redeem

Exchange activation code for JWT.

Request:

{
"code": "MYAPP-AB3D-EF5G",
"device_id": "machine-id-hash",
"device_type": "machine"
}

Response:

{
"token": "eyJhbGciOiJFZDI1NTE5...",
"expires_at": 1704070800
}

POST /activation/request-code

Request activation code sent to purchase email.

Request:

{
"email": "user@example.com",
"public_key": "-----BEGIN PUBLIC KEY-----..."
}

Response:

{
"message": "If a license exists for this email, a code has been sent"
}

Rate limited to 3 requests per email per hour.


POST /refresh

Refresh an existing JWT.

Headers:

Authorization: Bearer <current_jwt>

Response:

{
"token": "eyJhbGciOiJFZDI1NTE5...",
"expires_at": 1704070800
}

GET /license

Get license info from JWT.

Query Parameters:

  • token - The JWT
  • public_key - Project public key (for verification)

Response:

{
"valid": true,
"license_id": "lic_xxxxx",
"tier": "pro",
"features": ["export", "sync"],
"license_exp": null,
"updates_exp": 1735689600,
"device_id": "machine-id-hash",
"device_type": "machine"
}

POST /validate

Online license validation.

Headers:

Authorization: Bearer <jwt>

Response:

{
"valid": true,
"revoked": false,
"license_exp": null
}

POST /devices/deactivate

Self-deactivate current device.

Headers:

Authorization: Bearer <jwt>

Response:

{
"message": "Device deactivated"
}

POST /feedback

Submit user feedback.

Headers:

Authorization: Bearer <jwt>

Request:

{
"message": "Great app!",
"type": "feedback",
"email": "user@example.com",
"app_version": "1.2.3"
}

POST /crash

Report crash/error.

Headers:

Authorization: Bearer <jwt>

Request:

{
"error_type": "panic",
"error_message": "index out of bounds",
"stack_trace": "...",
"app_version": "1.2.3"
}

Webhook Endpoints

POST /webhook/stripe

Stripe webhook handler. Configure in Stripe Dashboard.

Events handled:

  • checkout.session.completed - Creates license
  • invoice.paid - Records renewal transaction
  • charge.refunded - Records refund transaction

POST /webhook/lemonsqueezy

LemonSqueezy webhook handler.

Events handled:

  • order_created - Creates license
  • subscription_payment_success - Records renewal
  • order_refunded - Records refund

Operator API

Requires operator-level API key.

Users

MethodEndpointDescription
POST/operators/usersCreate user
GET/operators/usersList users
GET/operators/users?email={email}Find by email
GET/operators/users/{id}Get user
PUT/operators/users/{id}Update user
DELETE/operators/users/{id}Delete user

Organizations

MethodEndpointDescription
POST/operators/organizationsCreate org
GET/operators/organizationsList orgs
GET/operators/organizations/{id}Get org
PUT/operators/organizations/{id}Update org
DELETE/operators/organizations/{id}Delete org

Operators

MethodEndpointDescription
POST/operatorsCreate operator
GET/operatorsList operators
GET/operators/{user_id}Get operator
PUT/operators/{user_id}Update operator
DELETE/operators/{user_id}Remove operator

API Keys (for Users)

MethodEndpointDescription
POST/operators/users/{user_id}/api-keysCreate key
GET/operators/users/{user_id}/api-keysList keys
DELETE/operators/users/{user_id}/api-keys/{key_id}Revoke key

Audit Logs

MethodEndpointDescription
GET/operators/audit-logsQuery logs (JSON)
GET/operators/audit-logs/textQuery logs (plain text)

Organization API

Requires org member API key.

Members

MethodEndpointDescription
POST/orgs/{org_id}/membersAdd member
GET/orgs/{org_id}/membersList members
GET/orgs/{org_id}/members/{user_id}Get member
PUT/orgs/{org_id}/members/{user_id}Update member
DELETE/orgs/{org_id}/members/{user_id}Remove member

Projects

MethodEndpointDescription
POST/orgs/{org_id}/projectsCreate project
GET/orgs/{org_id}/projectsList projects
GET/orgs/{org_id}/projects/{id}Get project
PUT/orgs/{org_id}/projects/{id}Update project
DELETE/orgs/{org_id}/projects/{id}Delete project

Products

MethodEndpointDescription
POST/orgs/{org_id}/projects/{id}/productsCreate product
GET/orgs/{org_id}/projects/{id}/productsList products
GET/orgs/{org_id}/projects/{id}/products/{pid}Get product
PUT/orgs/{org_id}/projects/{id}/products/{pid}Update product
DELETE/orgs/{org_id}/projects/{id}/products/{pid}Delete product

Licenses

MethodEndpointDescription
POST/orgs/{org_id}/projects/{id}/licensesCreate license
GET/orgs/{org_id}/projects/{id}/licensesList licenses
GET/orgs/{org_id}/projects/{id}/licenses/{lid}Get license
PATCH/orgs/{org_id}/projects/{id}/licenses/{lid}Update license
POST/orgs/{org_id}/projects/{id}/licenses/{lid}/revokeRevoke license
POST/orgs/{org_id}/projects/{id}/licenses/{lid}/send-codeSend activation code

Query filters for list:

  • email - Filter by purchase email
  • payment_provider_order_id - Filter by order ID

Devices

MethodEndpointDescription
DELETE/orgs/{org_id}/projects/{id}/licenses/{lid}/devices/{did}Deactivate device

Transactions

MethodEndpointDescription
GET/orgs/{org_id}/transactionsList org transactions
GET/orgs/{org_id}/transactions/statsOrg revenue stats
GET/orgs/{org_id}/projects/{id}/transactionsList project transactions
GET/orgs/{org_id}/projects/{id}/transactions/statsProject revenue stats
GET/orgs/{org_id}/projects/{id}/transactions/{tid}Get transaction
GET/orgs/{org_id}/projects/{id}/licenses/{lid}/transactionsLicense transactions

Operator Impersonation

Operators can access org endpoints on behalf of members:

GET /orgs/{org_id}/members
Authorization: Bearer pc_operator_key
X-On-Behalf-Of: {user_id}

Requires admin or owner operator role. The impersonated user must be a member of the org.


Error Responses

All errors return JSON:

{
"error": "invalid_code",
"message": "Activation code is invalid or expired"
}

Common Error Codes

CodeHTTP StatusDescription
invalid_code400Invalid activation code
code_expired400Activation code expired
device_limit_reached400Max devices activated
license_revoked400License has been revoked
unauthorized401Missing or invalid auth
forbidden403Insufficient permissions
not_found404Resource not found
rate_limited429Too many requests

Rate Limits

TierDefault RPMEndpoints
Strict10/buy, /activation/request-code
Standard30/callback, /redeem, /validate, etc.
Relaxed60/health
Org Ops3000/orgs/*

Rate limits are per-IP. Returns 429 Too Many Requests when exceeded.