Node / Python / Go
Inferio’s REST API is plain HTTP + JSON. Idiomatic SDKs for Node, Python, and Go are in development — sign up via the Developers section for the beta invite.
Until they ship, the snippets below show the recommended request idioms per language.
The browser is NOT a supported client. API tokens grant full read/write on your merchant; never embed them in a frontend bundle. Always proxy through your own server.
Node (axios)
import axios from "axios";
import FormData from "form-data";
import fs from "node:fs";
const inferio = axios.create({
baseURL: "https://api-dev.inferio.xyz",
headers: {
Authorization: `Bearer ${process.env.INFERIO_TOKEN}`,
"X-Merchant-ID": process.env.MERCHANT_ID,
},
});
// 1. Create upload session
const { data: session } = await inferio.post("/api/v1/ocr/upload-sessions");
// 2. Upload file
const form = new FormData();
form.append("files", fs.createReadStream("./sakura.pdf"));
await inferio.post(
`/api/v1/ocr/upload-sessions/${session.session_id}/files`,
form,
{ headers: form.getHeaders() },
);
// 3. Kick off OCR
const { data: request } = await inferio.post("/api/v1/ocr/requests", {
session_id: session.session_id,
document_type: "trade_invoice_jp",
webhook_url: process.env.WEBHOOK_URL,
});
console.log("queued →", request.id);Python (requests)
import os
import requests
BASE = "https://api-dev.inferio.xyz"
HEADERS = {
"Authorization": f"Bearer {os.environ['INFERIO_TOKEN']}",
"X-Merchant-ID": os.environ["MERCHANT_ID"],
}
# 1. Create upload session
session = requests.post(f"{BASE}/api/v1/ocr/upload-sessions", headers=HEADERS).json()
# 2. Upload file
with open("sakura.pdf", "rb") as f:
requests.post(
f"{BASE}/api/v1/ocr/upload-sessions/{session['session_id']}/files",
headers=HEADERS,
files={"files": f},
)
# 3. Kick off OCR
request = requests.post(
f"{BASE}/api/v1/ocr/requests",
headers={**HEADERS, "Content-Type": "application/json"},
json={
"session_id": session["session_id"],
"document_type": "trade_invoice_jp",
"webhook_url": os.environ["WEBHOOK_URL"],
},
).json()
print("queued →", request["id"])Go (net/http)
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
)
const base = "https://api-dev.inferio.xyz"
func setHeaders(req *http.Request) {
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFERIO_TOKEN"))
req.Header.Set("X-Merchant-ID", os.Getenv("MERCHANT_ID"))
}
func main() {
// 1. Create upload session
req, _ := http.NewRequest("POST", base+"/api/v1/ocr/upload-sessions", nil)
setHeaders(req)
res, _ := http.DefaultClient.Do(req)
var session struct{ SessionID string `json:"session_id"` }
json.NewDecoder(res.Body).Decode(&session)
// 2. Upload file
body := &bytes.Buffer{}
w := multipart.NewWriter(body)
f, _ := os.Open("sakura.pdf")
defer f.Close()
part, _ := w.CreateFormFile("files", "sakura.pdf")
io.Copy(part, f)
w.Close()
req2, _ := http.NewRequest("POST",
fmt.Sprintf("%s/api/v1/ocr/upload-sessions/%s/files", base, session.SessionID),
body)
setHeaders(req2)
req2.Header.Set("Content-Type", w.FormDataContentType())
http.DefaultClient.Do(req2)
// 3. Kick off OCR
payload, _ := json.Marshal(map[string]string{
"session_id": session.SessionID,
"document_type": "trade_invoice_jp",
"webhook_url": os.Getenv("WEBHOOK_URL"),
})
req3, _ := http.NewRequest("POST", base+"/api/v1/ocr/requests", bytes.NewReader(payload))
setHeaders(req3)
req3.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req3)
}Retry idioms
All three snippets above are happy-path. In production:
- Timeouts — set explicit client timeouts (Inferio responds in <500ms for control-plane endpoints; OCR happens async via webhook)
- Retries on 5xx + 429 — exponential backoff, 3 attempts; bail on 4xx (those are bugs, not transients)
- Idempotency-Key — pass
Idempotency-Key: <uuid>on retried POSTs to avoid double-creates
Coming SDK features
When the official SDKs ship, they’ll add:
- Built-in retry with idempotency keys
- Typed responses (TypeScript types, Python dataclasses, Go structs)
- Webhook helpers (signature verification, parsed event types)
- Streaming download for large extraction results
Until then, the REST API alone gets you to production.