Skip to main content

L402 API

Pay with Bitcoin, get AI results. Copy-paste the commands below.

Before You Start

Lightning Wallet

Phoenix, Muun, Wallet of Satoshi, Alby, or any LN wallet. Agents: CLW

Terminal or Tool

A command line, Postman, or lnget (recommended)

Private & No Signup

No account, no subscription, no personal data. Pay only when you use it

Want to try this without a terminal? Use Text Generation on the web — pay with any Lightning wallet, no setup needed.

Using the L402 Text Generation API

You can generate text responses by sending a POST request to our L402-protected text generation endpoint. This API supports conversational context and uses dynamic pricing based on your input length. Budget: 1,000 characters/Sat, min 4 Sats. Standard: 333 characters/Sat, min 5 Sats. Best: 100 characters/Sat, min 15 Sats. Follow the steps below, which include example `curl` commands.

API Endpoint: https://sats4ai.com/api/l402/generate-text

Step 1: Initial Request (to get Macaroon and Invoice)

First, make a request to the API with your text generation parameters, including the conversation history if any. This initial request will not generate the text yet; instead, the server calculates the price based on your input length and returns a 402 Payment Required status along with the L402 headers (a macaroon and a Lightning invoice priced accordingly).

Example `curl` command:

curl -X POST https://sats4ai.com/api/l402/generate-text \
-H "Content-Type: application/json" \
-d '{"input":[{"role":"User","content":"Tell me a story of a bird"},{"role":"Assistant","content":"Once upon a time, there was a little bird who loved to sing..."},{"role":"User","content":"What happened next?"}]}' \
-i

Explanation of the command:

  • -X POST: Specifies an HTTP POST request.
  • https://sats4ai.com/api/l402/generate-text: The target API URL.
  • -H "Content-Type: application/json": Indicates the request body is JSON.
  • -d '{...}': The JSON data payload with your text generation preferences (see "Request Body Parameters" below for details).
  • -i: Tells `curl` to include HTTP response headers in the output.

Expected Response Headers:

You will receive an HTTP/1.1 402 Payment Required response. Look for the www-authenticate header:

www-authenticate: L402 macaroon="<YOUR_MACAROON_STRING_HERE>", invoice="<YOUR_LIGHTNING_INVOICE_HERE>"
  • <YOUR_MACAROON_STRING_HERE>: Your unique access token.
  • <YOUR_LIGHTNING_INVOICE_HERE>: The Lightning Network invoice to pay.

Step 2: Pay the Lightning Invoice

Copy the <YOUR_LIGHTNING_INVOICE_HERE> string and pay it using any Lightning-enabled Bitcoin wallet. Upon successful payment, your wallet will provide you with a preimage (your proof of payment).

Step 3: Final Request (to get the Text Response)

Once you have the macaroon (from Step 1) and the preimage (from Step 2), make the exact same POST request again. This time, include an Authorization header.

Important: The JSON data payload (-d '{...}') in this second request must be identical to the one sent in Step 1.

Example `curl` command:

curl -X POST https://sats4ai.com/api/l402/generate-text \
-H "Content-Type: application/json" \
-H "Authorization: L402 <YOUR_MACAROON_STRING_HERE>:<YOUR_PREIMAGE_HERE>" \
-d '{"input":[{"role":"User","content":"Tell me a story of a bird"},{"role":"Assistant","content":"Once upon a time, there was a little bird who loved to sing..."},{"role":"User","content":"What happened next?"}]}'

Explanation of changes:

  • Replace <YOUR_MACAROON_STRING_HERE> with the macaroon from Step 1.
  • Replace <YOUR_PREIMAGE_HERE> with the preimage from Step 2.
  • The -H "Authorization: L402 <macaroon>:<preimage>" header is added.

Expected Successful Response:

If the L402 authentication is valid, the API will process your request and return the AI model's text response directly in the response body (typically as a JSON string or plain text, depending on your API's specific output for this endpoint). For instance, it might be a JSON object like:

The little bird soared higher, discovering a hidden valley full of musical flowers.

Request Body Parameters

The POST request body should be a JSON object with the following structure:

{
  "input": [
    {
      "role": "User",
      "content": "Tell me a story of a bird"
    },
    {
      "role": "Assistant",
      "content": "Once upon a time, there was a little bird who loved to sing..."
    },
    {
      "role": "User",
      "content": "What happened next?"
    }
  ]
}

modelId: number or string (optional)

Selects the text generation model. Omit for the best default model.

Accepted values: "best", "standard", "budget" (tier aliases), or a numeric model ID (e.g. 6, 1).

See available text models for IDs and pricing. Legacy model field ("Best", "Standard") is still accepted.

input: array of objects

The input array contains objects representing the conversation history. Each object must have a role and content field. The order of messages should reflect the flow of conversation.

Object structure within input array:

role: string

Indicates who sent the message.

Accepted Values: "User", "Assistant"

content: string

The actual text content of the message.

Example:

{
  "role": "User",
  "content": "Tell me a story of a bird"
}

fileContext: string (optional)

Extracted text content from a file (PDF, DOCX, XLSX, code, etc.) to include as context for the conversation. The file text is prepended to the last user message. Its length is included in the dynamic pricing calculation.

Works with both best and standard tier models.

fileName: string (optional)

The original filename of the attached file. Used as a label in the prompt context (e.g., [File: report.pdf]).

imageData: string (optional, best model only)

A base64 data URI of an image (e.g., data:image/png;base64,iVBOR...) for visual analysis. The default best model supports native multimodal vision input. This parameter is rejected for standard tier requests.

File & Image Attachment Examples

You can attach files or images alongside your conversation. Extract text from files client-side and send as fileContext, or send images as base64 data URIs via imageData (Best model only).

Text file attachment:

{
  "input": [
    {
      "role": "User",
      "content": "Summarize this document"
    }
  ],
  "fileContext": "Full extracted text of the file...",
  "fileName": "report.pdf"
}

Image analysis (best tier model only):

{
  "input": [
    {
      "role": "User",
      "content": "What is in this image?"
    }
  ],
  "imageData": "data:image/png;base64,iVBOR..."
}

Supported file types for fileContext: PDF, DOCX, XLSX, TXT, and code files. Supported image formats for imageData: PNG, JPG, JPEG, GIF, WebP (max 10 MB). File content length is added to the character count for dynamic pricing.