---
title: "Start a checkout"
method: POST
path: "/api/v1/billing/checkout"
tags: ["billing"]
---

# Start a checkout

`POST /api/v1/billing/checkout`

## Request

- Base URL: `https://api.sytecheck.app` (the document declares no server; this is the origin it was published from)
- URL: `https://api.sytecheck.app/api/v1/billing/checkout`
- Auth: HTTP bearer

Begin a checkout for a plan or a one-off scan, returning a transaction to complete in the browser.

## Headers

- `accept-language` string, nullable

## Request body

- CheckoutRequest: What the customer wants to buy. Either a subscription (`plan` + `period`) or the one-off audit (`product="one_off_scan"`). Prices are never sent by the client — the server resolves the Paddle price id from the plan table, so a tampered request buys nothing unexpected.
  - `product` 'subscription' | 'one_off_scan'
  - `plan` 'free' | 'pro' | 'agency', nullable: Tier to subscribe to: "pro" or "agency".
  - `period` 'monthly' | 'annual': Billing period: "monthly" or "annual".

## Response `200`

Successful Response

- CheckoutResponse: A Paddle transaction to hand to `Paddle.Checkout.open({ transactionId })`. The browser gets only this opaque id. The account the payment credits is set server-side in the transaction's `custom_data`, so it cannot be nominated by the client.
  - `transaction_id` string, required

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/sytecheck/apis/sytecheck-api.md) · [All operations](https://skmtc.dev/sytecheck/apis/sytecheck-api/llms.txt) · [OpenAPI document](https://skmtc.dev/sytecheck/apis/sytecheck-api/revisions/797cf6b3e867?raw)
