OpenAPI

The Aion API is documented in OpenAPI 3.1 format. Use the spec to generate clients, validate requests, or explore the API contract.

Spec

Download the OpenAPI spec:

/openapi.yaml

Generate client

You can use the OpenAPI spec to generate a typed client. First, download the spec or reference it by URL:

curl -o openapi.yaml https://payaion.com/openapi.yaml

JavaScript/TypeScript

npx openapi-typescript https://payaion.com/openapi.yaml -o payaion.d.ts

Python

pip install openapi-python-client
openapi-python-client generate --url https://payaion.com/openapi.yaml

Go

go install github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen@latest
oapi-codegen -package payaion openapi.yaml > payaion.go

Good to know: For JavaScript/TypeScript, openapi-typescript generates a type-only file (.d.ts) — it contains no executable code. You still write HTTP requests yourself (with fetch, axios, etc.), but every response is fully typed instead of unknown.

Using the TypeScript types

After running the npx openapi-typescript command above, you get a payaion.d.ts file with an operations type that maps every API endpoint to its request and response shapes.

1. Extract the types you need

import type { operations } from "./payaion";

// Upload (POST /v1/aion/upload)
type UploadResponse =
  operations["agentUpload"]["responses"]["202"]["content"]["application/json"];
// → { uploadId: string; status: "PENDING_UPLOAD"; statusUrl: string; downloadUrl: string; expiresAt: string }

type UploadError =
  operations["agentUpload"]["responses"]["400"]["content"]["application/json"];
// → { error: { code: string; message: string; retryAfterSec?: number } }

// Status (GET /v1/upload/{id}/status)
type StatusResponse =
  operations["agentUploadStatus"]["responses"]["200"]["content"]["application/json"];
// → { uploadId: string; status: "PENDING_UPLOAD"|"UPLOADING"|"READY"|"FAILED"|"DELETING"|"DELETED"; ready: boolean; ... }

// Fresh download URL (POST /v1/upload/{id}/download-url)
type DownloadUrlResponse =
  operations["agentDownloadUrl"]["responses"]["200"]["content"]["application/json"];

The path follows the pattern: operations["<operationId>"]["responses"]["<status>"]["content"]["application/json"]. Operation IDs match the spec: agentUpload, agentUploadStatus, agentDownloadUrl.

2. Use them with fetch

import type { operations } from "./payaion";

type UploadResponse =
  operations["agentUpload"]["responses"]["202"]["content"]["application/json"];

async function upload(file: File, apiKey: string): Promise<UploadResponse> {
  const body = new FormData();
  body.append("file", file);

  const res = await fetch("https://payaion-api.fly.dev/v1/aion/upload", {
    method: "POST",
    headers: { "X-Aion-Key": apiKey },
    body,
  });

  if (!res.ok) throw new Error(`Upload failed: ${res.status}`);

  const data: UploadResponse = await res.json();

  // data.uploadId    → string  ✓
  // data.status      → "PENDING_UPLOAD" ✓
  // data.statusUrl   → string  ✓
  // data.downloadUrl → string  ✓
  // data.expiresAt   → string  ✓
  return data;
}

Without the generated types you would need to define these interfaces by hand or work with any. The types stay in sync with the API — re-run the command after spec updates.

Using the Python types

The openapi-python-client command from above generates a full client package with Pydantic models for every request and response. However, for multipart uploads you still call requests (or httpx) yourself. Below is a lightweight approach using TypedDict — no code generation needed.

1. Define response types

from __future__ import annotations
from typing import Literal, TypedDict

# Upload (POST /v1/aion/upload) — 202
class UploadResponse(TypedDict):
    uploadId: str
    status: Literal["PENDING_UPLOAD"]
    statusUrl: str
    downloadUrl: str
    expiresAt: str          # ISO 8601

# Error body (400, 401, 413, …)
class _ErrorDetail(TypedDict, total=False):
    code: str
    message: str
    retryAfterSec: int      # only on 429

class ApiError(TypedDict):
    error: _ErrorDetail

# Status (GET /v1/upload/{id}/status) — 200
class StatusResponse(TypedDict, total=False):
    uploadId: str
    status: Literal["PENDING_UPLOAD", "UPLOADING", "READY", "FAILED", "DELETING", "DELETED"]
    ready: bool
    updatedAt: str

# Fresh download URL (POST /v1/upload/{id}/download-url) — 200
class DownloadUrlResponse(TypedDict):
    uploadId: str
    downloadUrl: str
    expiresAt: str
    ready: bool

These shapes match the OpenAPI spec exactly. If you prefer auto-generation, openapi-python-client creates equivalent Pydantic models for you.

2. Use them with requests

import requests

def upload(path: str, api_key: str) -> UploadResponse:
    with open(path, "rb") as f:
        resp = requests.post(
            "https://payaion-api.fly.dev/v1/aion/upload",
            headers={"X-Aion-Key": api_key},
            files={"file": f},
        )
    resp.raise_for_status()

    data: UploadResponse = resp.json()

    # data["uploadId"]    → str  ✓
    # data["downloadUrl"] → str  ✓
    # data["expiresAt"]   → str  ✓
    return data

def check_status(upload_id: str, api_key: str) -> StatusResponse:
    resp = requests.get(
        f"https://payaion-api.fly.dev/v1/upload/{upload_id}/status",
        headers={"X-Aion-Key": api_key},
    )
    resp.raise_for_status()
    return resp.json()

With TypedDict your editor autocompletes data["downloadUrl"] and catches typos at type-check time (mypy / pyright).

Base URL

All endpoints use the same base URL:

https://payaion-api.fly.dev

Endpoints covered

  • POST /v1/aion/upload — Upload a file, get a download URL
  • POST /v1/aion/upload-url — Upload from a URL (for bots & webhooks)
  • GET /v1/upload/{id}/status — Check if the file is ready
  • POST /v1/upload/{id}/download-url — Get a fresh download URL

The spec includes request/response schemas, authentication requirements, error formats, and all status codes.