---
title: "Earnings & monetization · Scrape.ly Docs"
description: "Earnings, payouts, and monetization, acquisition, and debugging insights."
url: https://scrape.ly/docs/api-earnings
markdown: https://scrape.ly/docs/api-earnings.md
---

# Earnings & monetization

> Earnings, payouts, and monetization, acquisition, and debugging insights.

When other users run your paid public Actors, you earn part of the Actor fee they pay. These endpoints cover creator setup (terms and payout details), your earnings ledger, payout requests and statements, pricing changes, publish checks and reviews, and owner insights (monetization, acquisition, debugging). Paths are relative to `https://api.scrape.ly`. For the rules and the dashboard flow, see [Publish & monetize](https://scrape.ly/docs/publishing.md).

All endpoints require authentication. Earnings, creator, and payout endpoints require your account API key: run tokens, CI tokens, and x402 payments get `403 insufficient-permissions`. Terms, payout details, payout requests, and statements also reject OAuth app tokens.

How earnings work:

| Rule | Value |
| --- | --- |
| Your share | **80%** of the Actor fee paid with purchased credits. Scrape.ly keeps 20% |
| Free credits, your own runs | Earn nothing |
| Platform usage (compute, storage, proxy) | Not shared |
| Availability | **30 days** (14 in good standing) after the run settles. Checked hourly |
| Refunds and chargebacks | Reverse the earnings they funded with a negative `clawback` entry |
| Payouts | On request, by crypto or PayPal from **$25**, or by bank transfer from **$500**. One pending request at a time |
| First payout | Capped at **$500**. Request the rest once it's paid |
| Processing | Each request is reviewed and sent by hand. There is no fixed processing time |

Earnings are kept separate from your credit balance and are never spent on runs.

## Creator status

```
GET /v2/monetization/status
```

Everything the dashboard checklist shows: what you can do, what's missing, your balances, and the rules.

```bash
curl "https://api.scrape.ly/v2/monetization/status" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"
```

```json
{
  "data": {
    "suspended": false,
    "suspendedReason": null,
    "terms": {
      "currentVersion": "2026-10-01",
      "isDraft": false,
      "acceptedVersion": "2026-10-01",
      "acceptedAt": "2026-10-02T09:00:00.000Z"
    },
    "can": { "setPaidPricing": true, "publishPaid": true, "receivePayouts": true },
    "requirements": [
      { "id": "terms", "label": "Accept the Creator Terms", "state": "complete", "requiredFor": ["paid_pricing", "paid_publish"] },
      { "id": "email_verified", "label": "Verify your email address", "state": "external", "requiredFor": ["payouts"] },
      { "id": "public_profile", "label": "Make your profile public", "state": "complete", "requiredFor": ["paid_publish"] },
      {
        "id": "payout_details", "label": "Add payout details", "state": "complete", "requiredFor": ["payouts"],
        "details": { "method": "crypto", "destination": "USDT on TRON (TRC-20) TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "minimumUsd": 25, "heldUntil": null }
      }
    ],
    "balances": {
      "pendingNd": 12500000000, "availableNd": 45000000000, "paidOutNd": 0, "reservedNd": 0,
      "pendingUsd": 12.5, "availableUsd": 45.0, "paidOutUsd": 0, "reservedUsd": 0
    },
    "rules": {
      "revenueShare": 0.8,
      "holdDays": 30,
      "payoutMinimumUsd": 25,
      "firstPayoutCapUsd": 500,
      "priceIncreaseNoticeDays": 14,
      "payoutMethod": "crypto",
      "payoutMinimums": { "crypto": 25, "paypal": 25, "bank_transfer": 500 },
      "payoutMethods": [
        { "id": "crypto", "label": "Crypto", "minimumUsd": 25 },
        { "id": "paypal", "label": "PayPal", "minimumUsd": 25 },
        { "id": "bank_transfer", "label": "Bank transfer", "minimumUsd": 500 }
      ],
      "cryptoOptions": [{ "asset": "usdt", "network": "tron", "label": "USDT on TRON (TRC-20)" }],
      "destinationHoldHours": 72,
      "payoutsHeldUntil": null,
      "standardHoldDays": 30,
      "trustedHoldDays": 14,
      "trustedMinAccountAgeDays": 60,
      "trusted": false
    },
    "payoutRequest": {
      "available": true,
      "reason": null,
      "message": null,
      "maxAmountUsd": 45.0,
      "minimumUsd": 25,
      "shortfallUsd": null,
      "heldUntil": null,
      "capped": false,
      "pendingRequest": null
    },
    "timeline": {
      "nextAvailableAt": "2026-11-12T08:03:46.000Z",
      "nextAvailableUsd": 4.1,
      "minimumReachedAt": null,
      "isFirstPayout": true
    },
    "usage30d": { "feeRuns": 120, "earningRuns": 95, "freeCreditRuns": 25, "freeCreditFeeUsd": 1.85 }
  }
}
```

| Requirement `state` | Meaning |
| --- | --- |
| `complete` | Done |
| `incomplete` | Not started |
| `external` | Handled by your account sign-up (email verification) |

Requirements may carry `details`, for example `currentVersion` for the terms. For payout details: `method`, your `destination` in full, the method's `minimumUsd`, and `heldUntil` while a changed destination is on hold.

`rules.payoutMinimumUsd` is the minimum for your current method (`$25` before you choose one). `rules.cryptoOptions` lists every supported currency and network (the example shows one). `rules.payoutsHeldUntil` is set while a destination changed in the last `destinationHoldHours` is on hold (a first destination saved while your available balance is below the minimum isn't held). `rules.holdDays` is the hold for your new earnings: `trustedHoldDays` while `trusted` is true (at least one paid payout, account at least `trustedMinAccountAgeDays` old, not suspended, no takedown or rejected review), otherwise `standardHoldDays`.

`timeline` is computed from money you've already earned: `nextAvailableAt` and `nextAvailableUsd` are the next pending amount to become available, and `minimumReachedAt` is when your available balance reaches your method's minimum (`null` if it already has, or if it needs more earnings). `isFirstPayout` is true until a payout has been paid, while the first-payout cap applies.

`usage30d` counts runs of your Actors in the last 30 days that charged an Actor fee (`feeRuns`), the ones that earned you something (`earningRuns`), and the ones paid entirely with free or promotional credits (`freeCreditRuns`, with their fees in `freeCreditFeeUsd`), which earn nothing.

`balances.reservedUsd` is the amount held by your pending payout request. It's no longer in `availableUsd` and not yet in `paidOutUsd`, which counts sent payouts only.

`payoutRequest` tells you whether you can [request a payout](#payout-requests) now:

| Field | Meaning |
| --- | --- |
| `available` | `true` when a request would be accepted |
| `maxAmountUsd` | The default and largest amount you can request now: your available balance, or $500 for your first payout (`capped: true`). `null` while `available` is `false` |
| `minimumUsd` | The minimum for your method |
| `reason`, `message` | Why you can't request one, and a sentence to show. See below |
| `shortfallUsd` | With `below_minimum`, how much more available balance you need |
| `heldUntil` | When a new destination becomes active |
| `pendingRequest` | Your pending request, in the [payout request](#payout-requests) shape, or `null` |

| `reason` | Example `message` |
| --- | --- |
| `below_minimum` | $12.40 more needed for the PayPal minimum ($25). |
| `destination_on_hold` | New payout details become active on 2026-10-16 09:00 UTC. |
| `request_pending` | You have a pending payout request. Cancel it or wait until it is processed before requesting another. |
| `payout_details_missing` | Add your legal details and a payout destination under Billing → Payouts to request a payout. |
| `suspended` | Monetization is suspended on your account, so payouts are on hold. |

```api-test
{ "method": "GET", "path": "/v2/monetization/status" }
```

## Creator Terms

```
GET /v2/monetization/terms
POST /v2/monetization/terms/accept
```

`GET` returns the current terms: `version`, `title`, `effectiveDate`, `isDraft`, `format` (`markdown`), and `text`, plus your `accepted`, `acceptedVersion`, and `acceptedAt`.

`POST` accepts a version. Send the `version` you showed the user:

```bash
curl -X POST "https://api.scrape.ly/v2/monetization/terms/accept" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "version": "2026-10-17" }'
```

| Status | Meaning |
| --- | --- |
| `201` | Accepted. Returns `version`, `acceptedAt`, and `alreadyAccepted: false` |
| `200` | You had already accepted this version (`alreadyAccepted: true`) |
| `409 terms-version-outdated` | A newer version exists. `data.currentVersion` has it |

## Payout details

```
GET /v2/monetization/payout-profile
PUT /v2/monetization/payout-profile
```

`PUT` replaces your payout details: the payout `method`, its `destination`, and the statement details printed on your statements.

| Field | Required | Limits |
| --- | --- | --- |
| `method` | Yes | `crypto`, `paypal`, or `bank_transfer` |
| `destination` | When adding or changing the destination | An object with the fields for the method, below. Leave it out to keep the saved destination of the same method |
| `legalName` | Yes | 2–200 characters |
| `country` | Yes | Two-letter ISO 3166 code |
| `addressLine1` | Yes | Up to 200 characters |
| `addressLine2` | No | Up to 200 characters |
| `city` | Yes | Up to 100 characters |
| `postalCode` | No | Up to 32 characters |
| `region` | No | Up to 100 characters |
| `vatId` | No | Up to 32 characters: letters, digits, spaces, dots, and dashes |

`destination` fields per method:

| Method | Field | Required | Limits |
| --- | --- | --- | --- |
| `paypal` | `email` | Yes | A valid email, up to 254 characters |
| `crypto` | `asset` | Yes | `usdt`, `usdc`, or `btc` |
| `crypto` | `network` | Yes | `usdt`: `tron`, `ethereum`, `polygon`, `solana`. `usdc`: `ethereum`, `polygon`, `base`, `solana`. `btc`: `bitcoin` |
| `crypto` | `address` | Yes | A valid address for the network, checksum included |
| `bank_transfer` | `accountHolderName` | Yes | 2–140 characters |
| `bank_transfer` | `iban` | One of `iban` or `accountNumber` | A valid IBAN: country length and check digits. Spaces are ignored |
| `bank_transfer` | `accountNumber` | One of `iban` or `accountNumber` | 4–34 letters and digits |
| `bank_transfer` | `routingCode` | No | ABA routing number, sort code, IFSC, BSB. 3–34 letters and digits |
| `bank_transfer` | `swiftBic` | Unless `iban` is from a SEPA country | 8 or 11 characters |
| `bank_transfer` | `bankName` | Yes | 2–140 characters |
| `bank_transfer` | `bankCountry` | Yes | Two-letter ISO 3166 code |
| `bank_transfer` | `holderAddress` | Yes | 5–300 characters |

```bash
curl -X PUT "https://api.scrape.ly/v2/monetization/payout-profile" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "method": "crypto",
    "destination": { "asset": "usdt", "network": "tron", "address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t" },
    "legalName": "Jane Doe", "country": "DE", "addressLine1": "Example Str. 1", "city": "Berlin"
  }'
```

Invalid fields return `400 invalid-input` with a per-field `data.errors` object, keyed `destination.<field>` for destination fields. `method` and `destination` are required.

`GET` and `PUT` return:

| Field | Meaning |
| --- | --- |
| `method` | The payout method, or `null` before you choose one |
| `destination` | Your destination in full, including the routing code and holder address for bank transfers. Includes a `summary` such as `Bank transfer DE89370400440532013000` |
| `details` | Your statement details |
| `minimumPayoutUsd` | The minimum for your method |
| `destinationChangedAt` | When the destination was last added or changed |
| `payoutsHeldUntil` | While a changed destination is on hold, when payouts to it start. Otherwise `null` |
| `destinationHoldHours` | `72` |
| `methods`, `cryptoOptions` | The methods with their minimums, and the supported crypto currencies and networks |
| `updatedAt` | When the payout details were last saved |

Statements, emails and the change log show the destination masked. Adding or changing a destination emails your account address. After a change you can't request a payout to it for 72 hours; a first destination saved while your available balance is below the minimum isn't held. A request you made before the change still goes to the destination it was made with. Saving the same destination again doesn't restart the hold. See [Changed destinations wait 72 hours](https://scrape.ly/docs/publishing.md#changed-destinations-wait-72-hours).

## Ledger

```
GET /v2/monetization/ledger
```

Every entry that changes your balance, newest first. Supports `limit` (default 20, max 100), `offset`, and `type` (comma-separated).

| `type` | Amount | Becomes available |
| --- | --- | --- |
| `earning` | Positive | 30 days after the run settled (14 in good standing) |
| `clawback` | Negative, after a refund or chargeback | Same date as the earning it reverses |
| `adjustment` | Either, a correction with a `reason` | Immediately |
| `payout` | Negative, the amount of a payout request, reserved when you make it | Immediately |
| `payout_reversal` | Positive, a cancelled or rejected request returned | Immediately |

Each item has `id`, `type`, `amountNd`, `amountUsd`, `availableAt`, `createdAt`, `actorId`, `actorName`, `runId`, `relatedEntryId` (the earning a clawback reverses), `payoutId`, `funding`, `source`, and `reason`. An unknown `type` returns `400`.

## Payout requests

```
POST /v2/monetization/payout-requests
GET /v2/monetization/payout-requests
GET /v2/monetization/payout-requests/{requestId}
POST /v2/monetization/payout-requests/{requestId}/cancel
```

You request a payout once your available balance reaches your method's minimum and your destination is out of its 72-hour hold. The request reserves the amount right away: it leaves your available balance as a `payout` ledger entry, so it can't be paid twice. You can have one pending request at a time. Scrape.ly reviews each request and sends it by hand to the method and destination saved on the request. There is no fixed processing time.

`POST` takes an optional `amountUsd` with up to two decimals. Leave it out to request `payoutRequest.maxAmountUsd` from the [status](#creator-status): your whole available balance, or $500 for your first payout.

```bash
curl -X POST "https://api.scrape.ly/v2/monetization/payout-requests" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "amountUsd": 45.00 }'
```

It returns `201` with the request:

```json
{
  "data": {
    "id": "pr_3f9c2a7e1b4d4c0e9a8f6b5d4c3b2a10",
    "amountNd": 45000000000,
    "amountUsd": 45.0,
    "capped": false,
    "status": "pending",
    "method": "crypto",
    "destination": "TR7NHq…Lj6t",
    "destinationLabel": "USDT on TRON (TRC-20) TR7NHq…Lj6t",
    "statementId": null,
    "createdAt": "2026-10-13T09:00:00.000Z",
    "requestedAt": "2026-10-13T09:00:00.000Z",
    "paidAt": null,
    "paymentReference": null,
    "amountSentUsd": null,
    "feeUsd": null,
    "rejectedReason": null,
    "processedAt": null,
    "cancellable": true
  }
}
```

| Field | Meaning |
| --- | --- |
| `amountUsd` | The amount reserved and to be paid |
| `capped` | The amount was limited by the $500 first-payout cap |
| `method`, `destination`, `destinationLabel` | Where the payout goes, masked. Saved when you made the request |
| `requestedAt` | When you made the request. `createdAt` is the same |
| `paidAt`, `paymentReference` | When it was sent, and the transaction ID or payment reference |
| `amountSentUsd`, `feeUsd` | What arrived and the transfer fee, when Scrape.ly records them |
| `rejectedReason` | Why a request was rejected |
| `processedAt` | When it was paid, rejected, or cancelled |
| `statementId` | The statement issued when it was paid |
| `cancellable` | You can still cancel it |

| `status` | Meaning |
| --- | --- |
| `pending` | Reserved and waiting to be sent |
| `paid` | Sent. A statement is issued |
| `rejected` | Not sent, with a `rejectedReason`. The amount is back in your available balance |
| `cancelled` | You cancelled it. The amount is back in your available balance |

`GET` lists your requests, newest first, with `items`, `total`, `offset`, and `limit` (default 20, max 100). `GET /v2/monetization/payouts` returns the same list.

`POST .../cancel` cancels a `pending` request and returns it with `status: "cancelled"`. Cancelling it again returns the same result. Scrape.ly emails you when a request is paid or rejected.

| Error | When |
| --- | --- |
| `409 payout-below-minimum` | Your available balance is below the minimum. `data` has `availableUsd`, `minimumUsd`, and `shortfallUsd` |
| `409 payout-destination-on-hold` | Your destination is in its 72-hour hold. `data.heldUntil` says until when |
| `409 payout-request-pending` | You already have a pending request. `data.requestId` has it |
| `409 payout-details-missing` | Your legal details or payout destination are missing |
| `403 monetization-suspended` | Monetization is suspended on your account |
| `400 invalid-input` | `amountUsd` isn't a positive number with up to two decimals, or is outside the minimum and `maxAmountUsd`. `data` has both |
| `404 payout-request-not-found` | Unknown request ID |
| `409 payout-request-state` | Cancelling a request that is already paid or rejected. `data.status` has its status |
| `409 payout-request-processing` | Cancelling a request that is already being sent |

```api-test
{ "method": "GET", "path": "/v2/monetization/payout-requests" }
```

## Statements

```
GET /v2/monetization/statements
GET /v2/monetization/statements/{statementId}
```

Statements are self-billing documents, one per paid request: `id`, `number` (`SCR-<year>-<sequence>`), `period` (`YYYY-MM`, the month it was paid), `payoutId`, `amountNd`, `amountUsd`, `currency`, `issuer`, `recipient` (your details when it was issued), `summary` (including `requestedAt`, `paidAt`, and `paymentReference`), `issuedAt`, and `voidedAt`. An unknown statement returns `404 statement-not-found`. The list supports `limit` and `offset`.

```api-test
{ "method": "GET", "path": "/v2/monetization/statements" }
```

## Pricing changes and reviews

```
GET /v2/actors/{actorId}/pricing-changes
DELETE /v2/actors/{actorId}/pricing-changes/{changeId}
GET /v2/actors/{actorId}/publish-checks
DELETE /v2/actors/{actorId}/publication-review
```

You change pricing with `PUT /v2/actors/{actorId}` and `pricingInfos`. Increases on an Actor with paying users are scheduled 14 days out, and some changes go to review. See [When pricing changes take effect](https://scrape.ly/docs/publishing.md#when-pricing-changes-take-effect) and [Manual review](https://scrape.ly/docs/publishing.md#manual-review).

- `pricing-changes` lists the Actor's changes: `id`, `status` (`scheduled`, `in_review`, `applied`, `cancelled`, `rejected`), `changeKind`, `noticeRequired`, `details`, `newPricingInfos`, and the effective date.
- `DELETE .../pricing-changes/{changeId}` cancels a `scheduled` or `in_review` change.
- `publish-checks` runs the publish checks without publishing.
- `DELETE .../publication-review` withdraws a pending review and returns `204`.

For Actors you don't own, these return `404 actor-not-found`.

## Earnings overview

These endpoints read from the same ledger as the creator endpoints.

### Summary

```
GET /v2/earnings
```

Without `type`, returns a summary plus the first 5 items of each category (incoming, available, withdrawn).

```bash
curl "https://api.scrape.ly/v2/earnings" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"
```

| Query param | Type | Default | Description |
| --- | --- | --- | --- |
| `type` | string | — | `incoming`, `available`, or `withdrawn`. Invalid values return `400 invalid-request`. |
| `limit` | number | 20 | Page size (max 100), used with `type`. |
| `offset` | number | 0 | Pagination offset, used with `type`. |

```json
{
  "data": {
    "summary": {
      "incoming": { "totalNd": 12500000000, "totalUsd": 12.5, "count": 3 },
      "available": { "totalNd": 45000000000, "totalUsd": 45.0, "count": 5 },
      "paidOut": { "totalNd": 30000000000, "totalUsd": 30.0 }
    },
    "incoming": { "items": [], "total": 3, "hasMore": false },
    "available": { "items": [], "total": 5, "hasMore": false },
    "withdrawn": { "items": [], "total": 2, "hasMore": false },
    "minWithdrawalUsd": 25
  }
}
```

With `type`, the response is `summary` plus a fully paginated `items` array, `total`, `offset`, `limit`, and `minWithdrawalUsd`. Each earning item includes `id`, `userId`, `actorId`, `actorName`, `runId`, `amountNd`, `amountUsd`, `createdAt`, `availableAt`, `status` (`pending`, `available`, or `withdrawn`), `withdrawnAt`, and `withdrawalId`.

- `summary.incoming` and `summary.available` are your pending and available balances, after clawbacks and adjustments.
- `withdrawn` items are the `payout` ledger entries of requests that have been paid. Pending, cancelled, and rejected requests aren't listed; see [Payout requests](#payout-requests). `summary.paidOut` is the total actually paid out: it leaves out pending requests, and a cancelled or rejected request nets to zero with its `payout_reversal`.
- `minWithdrawalUsd` is the payout minimum for your method.

```api-test
{ "method": "GET", "path": "/v2/earnings" }
```

### Incoming earnings

```
GET /v2/earnings/incoming
```

Pending credits still in the 30-day holding period. Supports `limit` / `offset` (max 100). Includes `summary` plus paginated `items`.

```bash
curl "https://api.scrape.ly/v2/earnings/incoming?limit=20&offset=0" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"
```

```api-test
{ "method": "GET", "path": "/v2/earnings/incoming?limit=5" }
```

### Available earnings

```
GET /v2/earnings/available
```

Earnings past their hold, which you can [request as a payout](#payout-requests). Same pagination. Includes `summary`, `items`, and `minWithdrawalUsd`.

```bash
curl "https://api.scrape.ly/v2/earnings/available" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"
```

```api-test
{ "method": "GET", "path": "/v2/earnings/available?limit=5" }
```

### Get a single earning

```
GET /v2/earnings/{earningId}
```

Returns one earning you own. Unknown IDs return `404 not-found`.

```bash
curl "https://api.scrape.ly/v2/earnings/{earningId}" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"
```

## Monetization insights

Owner-only stats for how much you earned from other users running your Actors. Amounts are USD. `month` is `YYYY-MM` (or a name like `August 2026`); it defaults to the current month, and an unrecognized value also falls back to the current month.

All insight endpoints (monetization, acquisition, debugging) are cached for 5 minutes.

### Per-Actor monetization

```
GET /v2/actors/{actorId}/monetization?month=YYYY-MM
```

```bash
curl "https://api.scrape.ly/v2/actors/{actorId}/monetization?month=2026-08" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"
```

Only the Actor owner can access this (`403 forbidden` otherwise; `404 actor-not-found` if the Actor does not exist).

```json
{
  "data": {
    "totalRevenue": 12.5,
    "totalActorFee": 18.0,
    "totalUsage": 18.0,
    "costPerResult": { "average": 0.01, "minimum": 0, "maximum": 0.04 },
    "dailyResults": { "average": 100, "minimum": 0, "maximum": 400 },
    "dailyRuns": { "average": 8, "minimum": 0, "maximum": 20 },
    "totalUsers": 14,
    "payingUsers": 14,
    "dailyBreakdown": [
      { "date": "2026-08-01", "runs": 4, "results": 80, "revenue": 0.4 }
    ]
  }
}
```

| Field | Meaning |
| --- | --- |
| `totalRevenue` | Your share (80%) of Actor fees for the month. |
| `totalActorFee` | Gross Actor fees users paid. `totalUsage` currently equals this. |
| `totalUsers` | Distinct users other than you who ran the Actor that month. `payingUsers` currently equals this. |
| `dailyBreakdown[].revenue` | Your share for that day. |

### Aggregated monetization

```
GET /v2/monetization?month=YYYY-MM
```

Same payload, aggregated across all Actors you own.

```bash
curl "https://api.scrape.ly/v2/monetization?month=2026-08" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"
```

```api-test
{ "method": "GET", "path": "/v2/monetization" }
```

## Acquisition insights

Page-view funnel for the last 30 days (unique sessions): detail, input, and run views, plus top referrer domains. Owner-only.

### Per-Actor acquisition

```
GET /v2/actors/{actorId}/acquisition
```

```bash [Request]
curl "https://api.scrape.ly/v2/actors/{actorId}/acquisition" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"
```

```json [Response]
{
  "data": {
    "totalVisitors": 240,
    "detailViews": 200,
    "inputViews": 80,
    "runViews": 40,
    "referrers": [
      { "domain": "google.com", "count": 90, "percentage": 60 }
    ]
  }
}
```

### Aggregated acquisition

```
GET /v2/acquisition
```

Same payload across all Actors you own.

```bash
curl "https://api.scrape.ly/v2/acquisition" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"
```

```api-test
{ "method": "GET", "path": "/v2/acquisition" }
```

## Debugging insights

Owner-only run-quality stats for **other users'** runs of your Actors (your own runs are excluded). Failed includes `FAILED` and `TIMED-OUT`.

`month` is `YYYY-MM`. If omitted, debugging uses a rolling **last 30 days** (unlike monetization, which defaults to the calendar month).

### Per-Actor debugging

```
GET /v2/actors/{actorId}/debugging?month=YYYY-MM
```

```bash [Request]
curl "https://api.scrape.ly/v2/actors/{actorId}/debugging?month=2026-08" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"
```

```json [Response]
{
  "data": {
    "successRate": 94,
    "successfulRuns": 188,
    "failedRuns": 10,
    "abortedRuns": 2,
    "avgDuration": 42,
    "dailySuccessRate": [
      { "date": "2026-08-01", "value": 96 }
    ]
  }
}
```

`avgDuration` is seconds. `successRate` and daily `value` are percentages (0–100).

### Aggregated debugging

```
GET /v2/debugging?month=YYYY-MM
```

Same payload across all Actors you own.

```bash
curl "https://api.scrape.ly/v2/debugging" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"
```

```api-test
{ "method": "GET", "path": "/v2/debugging" }
```

## Errors

| Status | Type | Meaning |
| --- | --- | --- |
| 400 | `invalid-request` | `type` is not `incoming`, `available`, or `withdrawn` |
| 400 | `invalid-input` | Invalid payout details (see `data.errors`), an invalid payout `amountUsd`, unknown ledger `type`, or missing terms `version` |
| 403 | `forbidden` | Insights for an Actor you do not own |
| 403 | `insufficient-permissions` | A run, CI, x402, or OAuth token where the account API key is required |
| 403 | `monetization-suspended` | Requesting a payout while monetization is suspended |
| 404 | `actor-not-found` / `not-found` | Unknown Actor or earning ID |
| 404 | `statement-not-found` / `payout-request-not-found` / `review-not-found` / `pricing-change-not-found` | Unknown statement or payout request, no pending review, or unknown pricing change |
| 409 | `payout-below-minimum` / `payout-destination-on-hold` / `payout-request-pending` / `payout-details-missing` | A payout can't be requested yet. See [Payout requests](#payout-requests) |
| 409 | `payout-request-state` / `payout-request-processing` | The payout request can't be cancelled anymore |
| 409 | `terms-version-outdated` | The terms version you accepted isn't the current one |
| 409 | `pricing-change-not-cancellable` | The pricing change is already applied, cancelled, or rejected |

---

- Previous: [Store, reviews & issues](https://scrape.ly/docs/api-store.md)
- Next: [Messages & notifications](https://scrape.ly/docs/api-messaging.md)
- All docs: [Docs index](https://scrape.ly/docs.md), [llms.txt](https://scrape.ly/llms.txt)
