Recoup

Get started with Recoup.

API REFERENCE

Social scrape

On this page
POST/api/socials/{id}/scrape

Trigger a scrape of one social profile. Use Get Artist Socials first to get the social id. The response contains scraper run metadata; poll it with the Scraper Results API.

Credits: 50,000 + 10,000 × posts micro-dollar credits per profile: $0.05 base + $0.01 per requested post. Omitting posts charges the 50,000 base, even when the selected platform fetches a default depth.

What posts does per platform

PlatformpostsWhen posts is omitted
Instagramignoredthe profile's latest posts (up to 12), always
TikTokresultsPerPage1 video
YouTubemaxResults, maxResultsShorts, maxResultStreams (per content type)1 video, 0 Shorts, 0 streams
X / Twittertimeline items; retweets and replies are fetched but not stored10 timeline items before filtering
LinkedInmaxPosts on the posts actor (runs instead of the profile actor)profile only, no posts
Threadsignoredprofile only
Facebookignoredprofile only

What gets stored. Webhook processing persists supported records from successful runs. Platform filtering, missing fields and budget-limited follow-ups can leave partial results:

- The profile: username, avatar, bio, follower and following counts, region. Served by Get Artist Socials. - One follower snapshot per social per day whenever the run reports a follower count (following and post counts too, where the platform reports them). Served by the history parameter of Get Artist Socials. - Every returned post with its engagement (views, likes, comments, reposts, where the platform reports them). Served by Get Artist Posts. - Instagram only: comments batches for already-known and newly discovered posts, then terminal profile batches for the returned commenters. Available profile fields are saved; completion and field coverage are not guaranteed. Served by Get Artist Fans.

Fan discovery is one hop deep. The commenter profile run is terminal: it never schedules comments or profile runs of its own. A normal single delivery can produce one profile run, two comments batches and two terminal commenter-profile batches. Five is a derived case, not a universal bound: retries, concurrent deliveries and budget checks affect the outcome. Budget checks are not atomic reservations and may allow overshoot; bookkeeping failures do not guarantee a hard cap. Pass subtitles=true on a YouTube social to include each video's transcript in the run results.

Authentication

x-api-key in header

bearerAuth bearer

Request

cURL
curl --request POST \
  --url 'https://api.recoupable.dev/api/socials/YOUR_ID/scrape' \
  --header 'x-api-key: YOUR_API_KEY'

Replace the YOUR_ placeholders with your values. Required query parameters are included; optional parameters are listed below.

Try it

Fill in the fields, send the request from your browser, and read the live response. The curl below updates as you type.

Kept in this browser tab only and cleared when it closes.

cURL for this request
curl --request POST \
  --url 'https://api.recoupable.dev/api/socials/{id}/scrape'

Parameters

Path parameters

idstringrequired

The unique identifier (UUID) of the social profile to scrape. Obtain this from the Get Artist Socials API.

Query parameters

postsinteger

Recent-post depth. Honored on TikTok, YouTube (per content type), X and LinkedIn; ignored on Instagram (always the profile's latest posts, up to 12), Threads and Facebook. Without it TikTok and YouTube use their single-item defaults; X fetches ten timeline items before filtering, so pass it whenever you need post history. Every returned post is stored with its engagement counts. See the per-platform table above.

subtitlesboolean

YouTube only. When true, the scrape also downloads each returned video's captions (auto-generated captions preferred, English, plain text). The transcript is returned on the run's dataset items as subtitles[0].plaintext and is not persisted; read it from Scraper Results while the run's dataset is available. Ignored on every other platform. Adds no credits beyond the posts price.

Default: false

Responses

200Scrape job triggered successfully

application/json

runIdstring

Unique identifier for the Apify run

datasetIdstring

Unique identifier for the dataset containing scraped data

errorstringnullable

Error message if the run failed (null if successful)

400Invalid path/query, malformed input or unsupported platform.

application/json

anyOf · SocialScrapeErrorResponse 1
statusstring · enum

Values: "error"

errorstringrequired
missing_fieldsarray<string | integer>
Item properties for missing_fields

string | integer

anyOf · object 2
runIdnullrequired
datasetIdnullrequired
errorstring · enumrequired

Values: "Unsupported social media platform"

401Missing, invalid or conflicting authentication headers.

application/json

statusstring · enum

Values: "error"

errorstringrequired
missing_fieldsarray<string | integer>
Item properties for missing_fields

string | integer

402Insufficient credits — the body includes a static billingUrl. No Stripe object is created.

application/json

errorstring · enumrequired

Values: "insufficient_credits"

remaining_creditsintegerrequired

Example: 0

required_creditsintegerrequired

Example: 250000

billingUrlstringrequired

Static link to the Recoup app, where a human can save a card and buy credits. It is a constant, not a freshly minted Stripe Checkout Session, so a credit-gated endpoint that keeps returning 402 creates nothing. To buy credits programmatically, call POST /api/credits/sessions.

Example: "https://app.recoupable.dev"

403The caller cannot access an artist linked to this social profile.

application/json

statusstring · enum

Values: "error"

errorstringrequired
missing_fieldsarray<string | integer>
Item properties for missing_fields

string | integer

404The social profile was not found.

application/json

statusstring · enum

Values: "error"

errorstringrequired
missing_fieldsarray<string | integer>
Item properties for missing_fields

string | integer

500Scraper startup, persistence or an internal operation failed.

application/json

statusstring · enum

Values: "error"

errorstringrequired
missing_fieldsarray<string | integer>
Item properties for missing_fields

string | integer

Full specification

Download the OpenAPI file for complete schemas, constraints, and examples.

Download social.json
View operation source
json
{
  "operationId": "postSocialsByIdScrape",
  "description": "Trigger a scrape of one social profile. Use [Get Artist Socials](/api-reference/artists/socials) first to get the social `id`. The response contains scraper run metadata; poll it with the [Scraper Results API](/api-reference/apify/scraper).\n\n**Credits:** `50,000 + 10,000 × posts` micro-dollar credits per profile: $0.05 base + $0.01 per requested post. Omitting `posts` charges the 50,000 base, even when the selected platform fetches a default depth.\n\n**What `posts` does per platform**\n\n| Platform | `posts` | When `posts` is omitted |\n|---|---|---|\n| Instagram | ignored | the profile's latest posts (up to 12), always |\n| TikTok | `resultsPerPage` | 1 video |\n| YouTube | `maxResults`, `maxResultsShorts`, `maxResultStreams` (per content type) | 1 video, 0 Shorts, 0 streams |\n| X / Twitter | timeline items; retweets and replies are fetched but not stored | 10 timeline items before filtering |\n| LinkedIn | `maxPosts` on the posts actor (runs instead of the profile actor) | profile only, no posts |\n| Threads | ignored | profile only |\n| Facebook | ignored | profile only |\n\n**What gets stored.** Webhook processing persists supported records from successful runs. Platform filtering, missing fields and budget-limited follow-ups can leave partial results:\n\n- The profile: username, avatar, bio, follower and following counts, region. Served by [Get Artist Socials](/api-reference/artists/socials).\n- One follower snapshot per social per day whenever the run reports a follower count (following and post counts too, where the platform reports them). Served by the `history` parameter of Get Artist Socials.\n- Every returned post with its engagement (`views`, `likes`, `comments`, `reposts`, where the platform reports them). Served by [Get Artist Posts](/api-reference/posts/get).\n- Instagram only: comments batches for already-known and newly discovered posts, then terminal profile batches for the returned commenters. Available profile fields are saved; completion and field coverage are not guaranteed. Served by [Get Artist Fans](/api-reference/fans/get).\n\n**Fan discovery is one hop deep.** The commenter profile run is terminal: it never schedules comments or profile runs of its own. A normal single delivery can produce one profile run, two comments batches and two terminal commenter-profile batches. Five is a derived case, not a universal bound: retries, concurrent deliveries and budget checks affect the outcome. Budget checks are not atomic reservations and may allow overshoot; bookkeeping failures do not guarantee a hard cap. Pass `subtitles=true` on a YouTube social to include each video's transcript in the run results.",
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "description": "The unique identifier (UUID) of the social profile to scrape. Obtain this from the [Get Artist Socials](/api-reference/artists/socials) API.",
      "required": true,
      "schema": {
        "type": "string",
        "format": "uuid"
      }
    },
    {
      "name": "posts",
      "in": "query",
      "description": "Recent-post depth. Honored on TikTok, YouTube (per content type), X and LinkedIn; ignored on Instagram (always the profile's latest posts, up to 12), Threads and Facebook. Without it TikTok and YouTube use their single-item defaults; X fetches ten timeline items before filtering, so pass it whenever you need post history. Every returned post is stored with its engagement counts. See the per-platform table above.",
      "required": false,
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 100
      },
      "example": 10
    },
    {
      "name": "subtitles",
      "in": "query",
      "required": false,
      "description": "YouTube only. When `true`, the scrape also downloads each returned video's captions (auto-generated captions preferred, English, plain text). The transcript is returned on the run's dataset items as `subtitles[0].plaintext` and is not persisted; read it from [Scraper Results](/api-reference/apify/scraper) while the run's dataset is available. Ignored on every other platform. Adds no credits beyond the `posts` price.",
      "schema": {
        "type": "boolean",
        "default": false
      }
    }
  ],
  "responses": {
    "200": {
      "description": "Scrape job triggered successfully",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ApifyRunResult"
          }
        }
      }
    },
    "400": {
      "description": "Invalid path/query, malformed input or unsupported platform.",
      "content": {
        "application/json": {
          "schema": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SocialScrapeErrorResponse"
              },
              {
                "type": "object",
                "required": [
                  "runId",
                  "datasetId",
                  "error"
                ],
                "properties": {
                  "runId": {
                    "type": "null"
                  },
                  "datasetId": {
                    "type": "null"
                  },
                  "error": {
                    "type": "string",
                    "enum": [
                      "Unsupported social media platform"
                    ]
                  }
                }
              }
            ]
          }
        }
      }
    },
    "401": {
      "description": "Missing, invalid or conflicting authentication headers.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/SocialScrapeErrorResponse"
          }
        }
      }
    },
    "402": {
      "description": "Insufficient credits — the body includes a static `billingUrl`. No Stripe object is created.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/SocialInsufficientCreditsResponse"
          }
        }
      }
    },
    "403": {
      "description": "The caller cannot access an artist linked to this social profile.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/SocialScrapeErrorResponse"
          }
        }
      }
    },
    "404": {
      "description": "The social profile was not found.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/SocialScrapeErrorResponse"
          }
        }
      }
    },
    "500": {
      "description": "Scraper startup, persistence or an internal operation failed.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/SocialScrapeErrorResponse"
          }
        }
      }
    }
  },
  "security": [
    {
      "apiKeyAuth": []
    },
    {
      "bearerAuth": []
    }
  ]
}