Quickstart

Two surfaces, one evidence model

Everything below runs against https://api.powerscraping.app. Whichever surface you use, the contract is the same: collection only runs against a declared authorized target, and every derived field in the result names the evidence it came from.

Authentication

Three credential kinds reach the same API, scoped to the same tenant.

Pick the credential that matches the caller.
Credential How it is presented Use it for
Session cookie psapp_session, set by /v1/auth/login, http-only The dashboard in a browser. Never used by server-side code.
API key Authorization: Bearer psa_live_… Your own backends, schedulers and scripts.
OAuth access token Authorization: Bearer with a JWT for audience /mcp The MCP connector, issued to an AI client after you consent.

An API key is shown exactly once, when you create it. Only its prefix and a hash are stored, so a lost key is revoked and replaced, never recovered.

Step 0: declare what you may collect

This is not paperwork you can defer. Managed collection is refused with collection_not_authorized until two things are true: your account has accepted the current acceptable-use version, and the handle is an active authorized target with a basis and a reference.

Valid values for authorization_basis.
Basis What it asserts Typical reference
own_account The profile belongs to your organisation. Internal account register entry
creator_contract You hold a signed agreement with the creator. Contract number and clause
client_mandate The account owner instructed you in writing. MSA or statement of work reference
public_interest_research Documented research in the public interest. Ethics approval or research protocol id

Revoke a target the moment its basis stops being true. Revocation takes effect immediately: the next job for that handle is refused.

REST API quickstart

Seven curl calls from nothing to citable records. The first four use a cookie jar because account and compliance actions need an interactive owner; the rest use an API key.

1. Create an account

curl -X POST https://api.powerscraping.app/v1/auth/signup \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{
        "email": "you@example.com",
        "password": "a-long-passphrase-you-chose",
        "organisation_name": "Acme Guides"
      }'

Passwords must be at least 12 characters. The response returns your tenant, user and plan, and sets the session cookie in cookies.txt.

2. Accept the acceptable-use terms

curl -X POST https://api.powerscraping.app/v1/legal/accept \
  -H "Content-Type: application/json" -b cookies.txt \
  -d '{"document": "acceptable_use"}'

Omit version and the current published version is recorded. Read it first at https://api.powerscraping.app/v1/legal/acceptable-use.

This is the one endpoint that insists on a signed-in user: the cookie from step 1, or the button in the dashboard. An API key or an MCP token is refused with permission_denied, because accepting the terms is the customer's own act and nothing running unattended may perform it on their behalf.

3. Declare an authorized target

curl -X POST https://api.powerscraping.app/v1/targets \
  -H "Content-Type: application/json" -b cookies.txt \
  -d '{
        "platform": "instagram",
        "username": "trattoriadaoscar",
        "authorization_basis": "client_mandate",
        "authorization_reference": "MSA-2026-114, schedule 2"
      }'

4. Mint an API key

curl -X POST https://api.powerscraping.app/v1/keys \
  -H "Content-Type: application/json" -b cookies.txt \
  -d '{"name": "ingest worker"}'
{
  "id": "key_7c1f…",
  "name": "ingest worker",
  "prefix": "psa_live_9Qd2",
  "active": true,
  "api_key": "psa_live_9Qd2………",
  "notice": "Copy this key now. It is shown once and cannot be retrieved again."
}

Export it for the calls below: export PSAPP_KEY=psa_live_9Qd2…. Store it in your secret manager, not in source control.

5. Submit a collection job

curl -X POST https://api.powerscraping.app/v1/jobs \
  -H "Authorization: Bearer $PSAPP_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: oscar-2026-09-17" \
  -d '{
        "kind": "collect",
        "target_username": "trattoriadaoscar",
        "platform": "instagram",
        "params": {"max_posts": 50, "include_comments": true}
      }'

Job kinds: collect (bounded recent posts), complete_history (Agency only), enrich_only (re-enrich the last release) and export (repackage a release). Re-sending the same Idempotency-Key returns the original job instead of starting a second one.

6. Poll the job

curl https://api.powerscraping.app/v1/jobs/job_5f2a \
  -H "Authorization: Bearer $PSAPP_KEY"
{
  "id": "job_5f2a",
  "kind": "collect",
  "target_username": "trattoriadaoscar",
  "status": "succeeded",
  "posts_processed": 48,
  "records_written": 48,
  "release_id": "rel_2026_09_17_01",
  "is_terminal": true,
  "results_available": true
}

Statuses are pending, running, succeeded, failed and cancelled. A job that ends with error_code: "access_blocked" met a challenge and stopped — that is the engine behaving correctly, not a bug to retry around.

7. Read the records

curl "https://api.powerscraping.app/v1/jobs/job_5f2a/results?limit=10&offset=0" \
  -H "Authorization: Bearer $PSAPP_KEY"

Reading a record and its citations

Each record carries its evidence items and the citations that bind fields to them. A field with no resolvable citation is not written at all, so a null means "we could not evidence this", never "we did not get round to it".

{
  "record_id": "rec_8d31f0a4",
  "source_url": "https://www.instagram.com/p/Cx1y2z3/",
  "creator_handle": "trattoriadaoscar",
  "venue": {"name": "Trattoria da Oscar", "place_id": "ChIJ7wV0mHrBhEcR8i0s"},
  "location": {"city": "Milan", "confidence": 0.94},
  "assessment": {"sentiment": "positive", "explicit_rating": null},
  "price": {"mentions_eur": [14.0, 22.0], "signal": "mid_range"},
  "unknown_fields": ["assessment.explicit_rating"],
  "citations": [
    {
      "field": "venue.name",
      "evidence_id": "ev_01",
      "modality": "caption",
      "excerpt": "finally back at @trattoriadaoscar for the cotoletta",
      "method": "caption_mention",
      "confidence": 0.97
    },
    {
      "field": "price.mentions_eur",
      "evidence_id": "ev_03",
      "modality": "caption",
      "excerpt": "cotoletta 22 euro, calice di rosso 14",
      "method": "price_extraction",
      "confidence": 0.93
    }
  ]
}

Every release also ships a provenance report (what was collected, when, under which authorization basis) and an exception report (what was refused, skipped or discarded, and why). Export both with an export job.

Errors

Every failure you can act on has the same shape and a stable machine-readable code.

{
  "error": {
    "code": "collection_not_authorized",
    "message": "No active authorized target for 'trattoriadaoscar' on instagram.",
    "detail": {"platform": "instagram", "username": "trattoriadaoscar"}
  }
}
The codes worth handling explicitly.
HTTP Code What to do
401 unauthenticated Present a valid credential. A revoked key reads the same as a missing one.
402 quota_exceeded The period allowance is spent. Enable overage or upgrade the plan.
403 collection_not_authorized Declare the target, or accept the current acceptable-use version - the latter from a signed-in session, not from a key or token.
403 permission_denied The action needs an account owner, not an API key.
404 not_found No such item in your tenant. Anything belonging to another tenant answers 404 as well, deliberately.
409 conflict Already declared, or the job has already finished and cannot be cancelled.
422 invalid_request Read detail.field; it names the offending field.
429 rate_limited Back off and retry.

MCP connector quickstart

The connector exposes the same evidence-grounded records to an AI client over the Model Context Protocol, Streamable HTTP transport, protocol revision 2025-06-18.

Add the server

In Claude, ChatGPT or an IDE agent that supports remote MCP servers, add a connector with this URL:

https://api.powerscraping.app/mcp

The client discovers authorization by itself: the server answers an unauthenticated call with 401 and a WWW-Authenticate header pointing at its RFC 9728 metadata. Registration, consent and token exchange then happen without you pasting a secret anywhere.

OAuth endpoints, for a client that needs them spelled out.
Purpose Path
Protected-resource metadata (RFC 9728) /.well-known/oauth-protected-resource
Authorization-server metadata (RFC 8414) /.well-known/oauth-authorization-server
Dynamic client registration (RFC 7591) /oauth/register
Authorization (PKCE required) /oauth/authorize
Token /oauth/token
Revocation (RFC 7009) /oauth/revoke

The tools

What the assistant can call once you have consented.
Tool What it does
list_authorized_targets The handles this account may collect, with basis and reference.
authorize_target Declare a new target, naming the basis and an auditable reference.
start_collection Submit a collection job for a declared target. Returns a job id.
get_job_status Poll the job, including the reason a job stopped.
get_venue_records Read a page of enriched records with their citations.
search_records Filter finished records by city, price band, sentiment or tag.
get_usage The plan, the period allowance and what is left of it.

A typical conversation

  1. list_authorized_targets to see what may be collected.
  2. authorize_target if the handle is missing — the basis is required.
  3. get_usage before a large run, so the job is not refused mid-way.
  4. start_collection, then get_job_status until it succeeds.
  5. get_venue_records or search_records to answer the question.

Tell the assistant to quote citations rather than fill gaps. When a field comes back null it is genuinely unknown, and the whole point of this connector is that the model can say so.

Endpoint reference

The full generated specification lives at https://api.powerscraping.app/api/openapi.json, with interactive docs at https://api.powerscraping.app/api/docs.

The endpoints this quickstart uses.
Method and path Credential Purpose
GET /v1/plans None The published plan catalogue.
GET /v1/legal/acceptable-use None The current terms and their version.
POST /v1/auth/signup None Create a tenant and its owner.
POST /v1/auth/login None Start a dashboard session.
POST /v1/legal/accept Session only Record acceptance of a policy version. An API key or an MCP token is refused with permission_denied, deliberately: this row is the account's proof of who agreed to the terms and when, so an unattended agent must not be able to bind the customer to them.
GET /v1/me Any The account, plan and usage behind the credential.
GET POST /v1/targets Session (write), any (read) List or declare authorized targets.
DELETE /v1/targets/{id} Session Revoke a declaration.
GET POST /v1/keys Session (owner) List or create API keys.
DELETE /v1/keys/{id} Session (owner) Revoke a key.
GET POST /v1/jobs Any List or submit jobs.
POST /v1/jobs/{id}/cancel Any Cancel a job that has not finished.
GET /v1/jobs/{id}/results Any A page of records with citations.
GET /v1/billing/usage Any Metered position and estimated overage.
POST /v1/billing/checkout Session (owner) Open Stripe Checkout for a paid plan.
POST /v1/billing/portal Session (owner) Open the Stripe billing portal.
POST /mcp OAuth bearer The MCP connector endpoint.