REST API v1

API Reference

Convert AFP (Advanced Function Presentation) files to PDF via a single HTTP endpoint. No dependencies, no setup — just send a file, get a PDF back.

Overview

How it works

One endpoint. Send your AFP file, receive a PDF binary. That's it.

ℹ️
Base URL: https://scribo-i9ld.polsia.app
All endpoints accept and return JSON for metadata. The conversion endpoint returns a raw PDF binary.

Scribo accepts AFP files in two upload modes:

  • Raw binary — send the AFP file as the request body with Content-Type: application/octet-stream
  • Multipart form — send as a standard file upload with Content-Type: multipart/form-data (field name: file)

On success, the response is a raw application/pdf binary with metadata in response headers (page count, processing time, document name).

Authentication

API keys

The conversion endpoint requires an API key. Pass it in the Authorization header as a Bearer token.

Authorization header
Authorization: Bearer sk_your_api_key_here

API keys look like sk_ followed by a 32-character hex string. Keep them secret — treat them like passwords.

Getting a key

Call POST /api/keys with your email address. Free-tier keys are issued instantly — no credit card required.

curl
curl -X POST \
  https://scribo-i9ld.polsia.app/api/keys \
  -H "Content-Type: application/json" \
  -d '{"email": "you@company.com"}'
201 Created
{
  "success": true,
  "api_key": "sk_3f7a2b1c8d4e9f0a1b2c3d4e5f6a7b8c",
  "plan": "free",
  "usage": 0,
  "limit": 100,
  "message": "API key created. Include it as: Authorization: Bearer sk_..."
}
💡
Already have a key? Calling POST /api/keys with the same email returns your existing key — so you don't need to store it anywhere special.
Free Tier

Get your API key

Free-tier keys are provisioned instantly. 100 conversions per month, no credit card.

Request a free API key

Instant · No credit card

Paste and run this in your terminal, replacing the email:

curl -X POST \
  https://scribo-i9ld.polsia.app/api/keys \
  -H "Content-Type: application/json" \
  -d '{"email": "you@company.com"}'

Your key arrives in the JSON response. Copy the api_key value.

Endpoints

POST /api/convert

Convert an AFP file to PDF. Requires an API key. Returns the PDF binary on success.

POST /api/convert Requires API key

Request headers

HeaderTypeDescription
Authorization required string Bearer token — Bearer sk_your_api_key
Content-Type optional string application/octet-stream for raw binary, or multipart/form-data for form upload. Auto-detected if omitted.

Request body

Send the AFP file as the raw request body (application/octet-stream) or as a multipart form upload with the field name file.

Maximum file size: 50 MB.

Response — 200 OK

On success, returns Content-Type: application/pdf with the PDF binary. Metadata is provided in response headers.

200 OK — PDF binary
# Response headers
Content-Type: application/pdf
Content-Disposition: attachment; filename="DOCNAME.pdf"
X-Page-Count: 4                  # number of pages in the PDF
X-Processing-Time-Ms: 8           # server-side conversion time (ms)
X-Document-Name: STMT_2024_Q4     # document name from AFP metadata
X-Renderer-Version: 2             # internal renderer version

Example: raw binary upload

curl — raw binary
curl -X POST \
  https://scribo-i9ld.polsia.app/api/convert \
  -H "Authorization: Bearer sk_your_api_key" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @document.afp \
  -o output.pdf

Example: multipart form upload

curl — multipart
curl -X POST \
  https://scribo-i9ld.polsia.app/api/convert \
  -H "Authorization: Bearer sk_your_api_key" \
  -F "file=@document.afp" \
  -o output.pdf
Endpoints

POST /api/demo/convert

Key-free demo conversion. No authentication required. Rate-limited by IP to prevent abuse.

POST /api/demo/convert No auth required

Same request format as POST /api/convert but no API key required. Intended for the browser-based demo on the landing page.

⚠️
Rate limit: 10 conversions per IP per hour. Use POST /api/convert with an API key for production workloads.

On success, returns the PDF binary inline (Content-Disposition: inline). Also sets X-Demo-Remaining in response headers to show how many demo calls remain.

curl — demo endpoint
curl -X POST \
  https://scribo-i9ld.polsia.app/api/demo/convert \
  -F "file=@document.afp" \
  -o preview.pdf
Endpoints

POST /api/keys

Generate or retrieve a free-tier API key. Idempotent — calling with the same email always returns the same key.

POST /api/keys No auth required

Request body (JSON)

FieldTypeDescription
email required string Your email address. Used to identify your key — no spam, no newsletter.
201 Created (or 200 if key already exists)
{
  "success": true,
  "api_key": "sk_3f7a2b1c8d4e9f0a1b2c3d4e5f6a7b8c",
  "plan": "free",
  "usage": 0,
  "limit": 100,
  "message": "API key created. Include it as: Authorization: Bearer sk_..."
}
Endpoints

GET /api/usage

Check how many conversions you've used this billing period and when your quota resets.

GET /api/usage Requires API key

Pass your API key as a Bearer token. Returns usage and plan details.

200 OK
{
  "success": true,
  "usage": 12,
  "limit": 100,
  "plan": "free",
  "resets_at": "2026-05-19T00:00:00.000Z"
}
curl
curl https://scribo-i9ld.polsia.app/api/usage \
  -H "Authorization: Bearer sk_your_api_key"
Reference

Rate limits

Limits are per API key and reset every 30 days.

Plan Conversions / Month Max File Size Support
Free 100 50 MB Community
Pro 10,000 50 MB Priority email
Demo (no key) 10 / hour (per IP) 50 MB

When you hit your limit, the API returns HTTP 429 with a JSON error and a resets_at timestamp. Contact us to upgrade to Pro.

📈
Need higher limits? scribo@polsia.app — Pro plan unlocks 10,000 conversions/month with priority support.
Reference

Error codes

All errors return JSON with a success: false field and a human-readable error message.

400
Bad Request Invalid or missing AFP file, file too small, wrong format (e.g. uploaded a PDF instead of AFP), or missing request body.
401
Unauthorized Missing or invalid API key. Check the Authorization header format: Bearer sk_your_key.
413
Payload Too Large File exceeds the 50 MB limit. Split large AFP jobs into smaller files.
429
Rate Limit Exceeded Monthly conversion quota reached. Response includes resets_at timestamp. Upgrade to Pro for 10,000/month.
500
Internal Error Unexpected server error during conversion. Rare — if it persists, contact scribo@polsia.app.
503
Service Unavailable Conversion module temporarily unavailable. Retry in a few seconds.

Error response shape

Error JSON
{
  "success": false,
  "error": "File does not appear to be in AFP format...",
  "details": []   // optional — parse error details for 400s
}
Reference

Response headers

On a successful conversion, these headers are set alongside the PDF binary:

HeaderDescription
X-Page-Count Number of pages in the rendered PDF.
X-Processing-Time-Ms Server-side conversion time in milliseconds.
X-Document-Name Document name extracted from AFP metadata.
X-Renderer-Version Internal AFP renderer version for debugging.
X-Demo-Remaining (/api/demo/convert only) Demo calls remaining this hour.
Code Examples

Integrate in minutes

Copy-paste examples for the most common languages. Replace sk_your_api_key with your actual key.

# Raw binary upload — saves result to output.pdf
curl -X POST \
  https://scribo-i9ld.polsia.app/api/convert \
  -H "Authorization: Bearer sk_your_api_key" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @document.afp \
  -o output.pdf

# Multipart form upload (easier for most shells)
curl -X POST \
  https://scribo-i9ld.polsia.app/api/convert \
  -H "Authorization: Bearer sk_your_api_key" \
  -F "file=@document.afp" \
  -o output.pdf
// Node.js 18+ — uses built-in fetch
import { readFileSync, writeFileSync } from 'fs';

const API_KEY = 'sk_your_api_key';
const afpData = readFileSync('./document.afp');

const response = await fetch('https://scribo-i9ld.polsia.app/api/convert', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type': 'application/octet-stream',
  },
  body: afpData,
});

if (!response.ok) {
  const err = await response.json();
  throw new Error(`Conversion failed: ${err.error}`);
}

// Save PDF to disk
const pdfBuffer = Buffer.from(await response.arrayBuffer());
writeFileSync('./output.pdf', pdfBuffer);

// Inspect metadata from headers
console.log('Pages:', response.headers.get('x-page-count'));
console.log('Time:', response.headers.get('x-processing-time-ms'), 'ms');
# pip install requests
import requests

API_KEY = "sk_your_api_key"

with open("document.afp", "rb") as f:
    afp_data = f.read()

response = requests.post(
    "https://scribo-i9ld.polsia.app/api/convert",
    headers={"Authorization": f"Bearer {API_KEY}"},
    data=afp_data,
    # or use files={"file": open("document.afp", "rb")} for multipart
)

response.raise_for_status()  # raises on 4xx/5xx

with open("output.pdf", "wb") as f:
    f.write(response.content)

print(f"Pages: {response.headers.get('X-Page-Count')}")
print(f"Time:  {response.headers.get('X-Processing-Time-Ms')}ms")
// Java 11+ HttpClient (built-in, no dependencies)
import java.net.URI;
import java.net.http.*;
import java.nio.file.*;

var client = HttpClient.newHttpClient();
var afpBytes = Files.readAllBytes(Path.of("document.afp"));

var request = HttpRequest.newBuilder()
    .uri(URI.create("https://scribo-i9ld.polsia.app/api/convert"))
    .header("Authorization", "Bearer sk_your_api_key")
    .header("Content-Type", "application/octet-stream")
    .POST(HttpRequest.BodyPublishers.ofByteArray(afpBytes))
    .build();

var response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());

if (response.statusCode() != 200) {
    throw new RuntimeException("Error: " + response.statusCode());
}

Files.write(Path.of("output.pdf"), response.body());

System.out.println("Pages: " + response.headers().firstValue("x-page-count").orElse("?"));
System.out.println("Time:  " + response.headers().firstValue("x-processing-time-ms").orElse("?") + "ms");
Try It

Interactive curl command

Paste your API key below to generate a ready-to-run curl command.

POST /api/convert

Paste your key, copy the command
curl -X POST \
  https://scribo-i9ld.polsia.app/api/convert \
  -H "Authorization: Bearer sk_your_api_key" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @document.afp \
  -o output.pdf

Replace document.afp with the path to your AFP file. Don't have an API key yet? Get one free →