API Reference

Query and mutate data with the type-safe tRPC API.

Overview

Parser Run uses tRPC for end-to-end type safety. Your IDE knows the exact shape of every response—no codegen required.

Client Setup
import { createTRPCClient, httpBatchLink } from "@trpc/client";
import type { AppRouter } from "@parser-run/trpc";

const trpc = createTRPCClient<AppRouter>({
  links: [
    httpBatchLink({
      url: "https://api.parser.run/trpc",
      headers: () => ({
        authorization: `Bearer ${apiKey}`,
      }),
    }),
  ],
});

Projects

Manage scraping projects.

List Projects

const { projects } = await trpc.projects.list.query({
  limit: 10,
  offset: 0,
  status: "active",  // optional filter
});

Get Project

const project = await trpc.projects.get.query({
  id: "nike-price-tracker",
});

Create Project

const project = await trpc.projects.create.mutate({
  name: "Competitor Prices",
  urls: ["https://competitor.com/products"],
  schema: {
    name: "text",
    price: "number",
    inStock: "boolean",
  },
  schedule: "daily",
});

Jobs

Monitor and control scraping jobs.

Start Job

const job = await trpc.scraper.runScrape.mutate({
  projectId: "nike-price-tracker",
});

// Returns job ID for status polling
console.log(job.id);  // "job_xyz789"

Get Job Status

const status = await trpc.scraper.getScrapeStatus.query({
  jobId: "job_xyz789",
});

// status.stage: "discovery" | "acquisition" | "parsing" | "complete" | "failed"
// status.progress: 0-100
// status.recordsExtracted: number

List Recent Jobs

const { jobs } = await trpc.scraper.listJobs.query({
  projectId: "nike-price-tracker",
  limit: 10,
});

Records

Query extracted data.

List Records

const { records, total } = await trpc.records.list.query({
  projectId: "nike-price-tracker",
  limit: 100,
  offset: 0,
  orderBy: "extractedAt",
  orderDir: "desc",
});

Query Records

const { records } = await trpc.records.query.query({
  projectId: "nike-price-tracker",
  filters: [
    { field: "price", operator: "lt", value: 100 },
    { field: "in_stock", operator: "eq", value: true },
  ],
  orderBy: "price",
  orderDir: "asc",
});

Export Records

const csv = await trpc.records.export.query({
  projectId: "nike-price-tracker",
  format: "csv",  // or "json"
});

Authentication

API requests require an API key. Generate keys in Settings → API Keys.

Example Request
curl -X POST https://api.parser.run/trpc/projects.list \
  -H "Authorization: Bearer pk_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{"limit": 10}'

Key types:

  • Read — Query projects, jobs, and records
  • Write — Create projects, start jobs
  • Admin — Full access including settings

Webhooks

Receive notifications when events occur.

Webhook Payload
// POST to your webhook URL
{
  event: "job.completed",
  timestamp: "2025-01-15T10:30:00Z",
  data: {
    projectId: "nike-price-tracker",
    jobId: "job_xyz789",
    recordsExtracted: 240,
    duration: 847,  // seconds
  }
}

// Event types:
// - job.started
// - job.completed
// - job.failed
// - alert.triggered

Error Handling

tRPC throws typed errors you can catch:

import { TRPCClientError } from "@trpc/client";

try {
  await trpc.projects.get.query({ id: "nonexistent" });
} catch (error) {
  if (error instanceof TRPCClientError) {
    console.log(error.message);     // "Project not found"
    console.log(error.data?.code);  // "NOT_FOUND"
  }
}

// Common error codes:
// - UNAUTHORIZED: Invalid or missing API key
// - NOT_FOUND: Resource doesn't exist
// - BAD_REQUEST: Invalid parameters
// - RATE_LIMITED: Too many requests

Rate Limits

API requests are rate limited by plan:

PlanRequests/minConcurrent Jobs
Starter601
Growth3005
Scale100020