Skip to content

Quickstart

Follow these steps to go from zero to a working dataset with an API key. The entire flow takes about five minutes.

Overview

sequenceDiagram
    participant You
    participant API as IPTO API
    participant S3 as Cloud Storage

    You->>API: 1. POST /v1/auth/signup
    API-->>You: session_token

    You->>API: 2. POST /v1/datasets
    API-->>You: dataset_id

    You->>API: 3a. POST /v1/datasets/{id}/objects/upload
    API-->>You: object_id + upload_url

    You->>S3: 3b. PUT upload_url (file body)
    S3-->>You: 200 OK

    You->>API: 3c. POST /v1/objects/{id}/confirm
    API-->>You: confirmed

    You->>API: 4. POST /v1/api-keys
    API-->>You: API key secret

Step 1: Sign Up

Create your account and tenant. The response includes a session token you will use for the remaining steps.

ipto login --email [email protected] --password your_password
curl -X POST https://api.ipto.ai/v1/auth/signup \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "your-secure-password",
    "display_name": "Jane Developer",
    "tenant_name": "Acme Corp"
  }'
import requests

resp = requests.post(
    "https://api.ipto.ai/v1/auth/signup",
    json={
        "email": "[email protected]",
        "password": "your-secure-password",
        "display_name": "Jane Developer",
        "tenant_name": "Acme Corp",
    },
)
data = resp.json()
token = data["session_token"]
print(f"Tenant: {data['tenant_id']}")
const res = await fetch("https://api.ipto.ai/v1/auth/signup", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    email: "[email protected]",
    password: "your-secure-password",
    display_name: "Jane Developer",
    tenant_name: "Acme Corp",
  }),
});
const data = await res.json();
const token = data.session_token;

Response:

{
  "user_id": "usr_abc123",
  "tenant_id": "tnt_xyz789",
  "session_token": "eyJhbGciOi..."
}

Step 2: Create a Dataset

Datasets are containers for your files. Give yours a name, description, and modality.

ipto datasets create --name "Research Papers" \
  --description "Academic papers" --modality document
curl -X POST https://api.ipto.ai/v1/datasets \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Q4 Invoices",
    "description": "Scanned invoice PDFs from Q4 2025",
    "source_modality": "document"
  }'
headers = {"Authorization": f"Bearer {token}"}

resp = requests.post(
    "https://api.ipto.ai/v1/datasets",
    headers=headers,
    json={
        "name": "Q4 Invoices",
        "description": "Scanned invoice PDFs from Q4 2025",
        "source_modality": "document",
    },
)
dataset_id = resp.json()["dataset_id"]
const headers = {
  Authorization: `Bearer ${token}`,
  "Content-Type": "application/json",
};

const dsRes = await fetch("https://api.ipto.ai/v1/datasets", {
  method: "POST",
  headers,
  body: JSON.stringify({
    name: "Q4 Invoices",
    description: "Scanned invoice PDFs from Q4 2025",
    source_modality: "document",
  }),
});
const { dataset_id } = await dsRes.json();

Response:

{
  "dataset_id": "dset_abc123",
  "status": "active",
  "created_at": "2026-04-05T10:00:00Z"
}

Step 3: Upload an Object

Uploading is a three-step flow: initiate, upload the file to the presigned URL, then confirm.

Using the CLI?

The CLI handles the entire 3-step presigned upload flow in a single command:

ipto objects upload dset_abc123 ./research-paper.pdf

3a. Initiate the Upload

curl -X POST https://api.ipto.ai/v1/datasets/$DATASET_ID/objects/upload \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "filename": "invoice-0042.pdf",
    "content_type": "application/pdf",
    "size_bytes": 184320
  }'
resp = requests.post(
    f"https://api.ipto.ai/v1/datasets/{dataset_id}/objects/upload",
    headers=headers,
    json={
        "filename": "invoice-0042.pdf",
        "content_type": "application/pdf",
        "size_bytes": 184320,
    },
)
upload = resp.json()
object_id = upload["object_id"]
upload_url = upload["upload_url"]
const uploadRes = await fetch(
  `https://api.ipto.ai/v1/datasets/${dataset_id}/objects/upload`,
  {
    method: "POST",
    headers,
    body: JSON.stringify({
      filename: "invoice-0042.pdf",
      content_type: "application/pdf",
      size_bytes: 184320,
    }),
  }
);
const { object_id, upload_url } = await uploadRes.json();

Response:

{
  "object_id": "obj_def456",
  "upload_url": "https://storage.example.com/presigned-put-url...",
  "expires_at": "2026-04-05T10:15:00Z"
}

3b. Upload the File

Send the raw file body to the presigned URL using a PUT request. No authorization header is needed -- the URL itself contains the credentials.

curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: application/pdf" \
  --data-binary @invoice-0042.pdf
with open("invoice-0042.pdf", "rb") as f:
    put_resp = requests.put(
        upload_url,
        data=f,
        headers={"Content-Type": "application/pdf"},
    )
assert put_resp.status_code == 200
import { readFile } from "fs/promises";

const fileData = await readFile("invoice-0042.pdf");
await fetch(upload_url, {
  method: "PUT",
  headers: { "Content-Type": "application/pdf" },
  body: fileData,
});

3c. Confirm the Upload

Tell IPTO the upload is complete so the object can proceed through the pipeline.

curl -X POST https://api.ipto.ai/v1/objects/$OBJECT_ID/confirm \
  -H "Authorization: Bearer $TOKEN"
resp = requests.post(
    f"https://api.ipto.ai/v1/objects/{object_id}/confirm",
    headers=headers,
)
print(resp.json())
await fetch(
  `https://api.ipto.ai/v1/objects/${object_id}/confirm`,
  {
    method: "POST",
    headers: { Authorization: `Bearer ${token}` },
  }
);

Response:

{
  "object_id": "obj_def456",
  "status": "confirmed"
}

What happens next?

After confirmation, your object enters the processing pipeline. Depending on the file type, this includes normalization, text extraction, and indexing. You can poll the object status via GET /v1/objects/{object_id}.


Step 4: Create an API Key

API keys let your agents and scripts access the API without a session token. Assign only the scopes your integration needs.

ipto keys create --name "Search Agent" \
  --scopes datasets:read,search:query
curl -X POST https://api.ipto.ai/v1/api-keys \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "search-agent-prod",
    "scopes": ["datasets:read", "search:query"]
  }'
resp = requests.post(
    "https://api.ipto.ai/v1/api-keys",
    headers=headers,
    json={
        "name": "search-agent-prod",
        "scopes": ["datasets:read", "search:query"],
    },
)
key_data = resp.json()
print(f"Save this secret: {key_data['secret']}")
const keyRes = await fetch("https://api.ipto.ai/v1/api-keys", {
  method: "POST",
  headers,
  body: JSON.stringify({
    name: "search-agent-prod",
    scopes: ["datasets:read", "search:query"],
  }),
});
const keyData = await keyRes.json();
console.log(`Save this secret: ${keyData.secret}`);

Response:

{
  "api_key_id": "key_ghi789",
  "name": "search-agent-prod",
  "scopes": ["datasets:read", "search:query"],
  "secret": "ipto_kp1a2b_sk_live_c3d4e5f6..."
}

Save your secret immediately

The API key secret is returned only once at creation time. Store it securely. If you lose it, revoke the key and create a new one.


Next Steps

You now have a tenant, a dataset with an uploaded object, and an API key. Here is where to go next:

  • Authentication -- Understand session tokens, API keys, and scopes in depth.
  • Concepts -- Learn the data model: tenants, datasets, objects, and search.
  • Searching Data -- Run your first hybrid search query.
  • Managing API Keys -- Rotate keys, restrict dataset access, and manage scopes.