Scrapely API is now live check it out here

Getting Started

The Scrapely API allows you to send direct messages and fetch conversations programmatically. Use it to integrate Twitter DM automation into your own applications and workflows.

Base URL

text
https://app.scrapely.co/api/v1

Available Endpoints

Accounts
GET/accountsList your Twitter accounts
POST/accountsAdd a new account
DELETE/accountsRemove an account
PUT/accounts/cookiesUpdate account cookies
Cookie Extraction
POST/get-cookiesQueue cookie extraction job
GET/get-cookies/statusCheck extraction status
Lead Scraping
POST/scraping-sourcesCreate a scraping source
GET/scraping-sourcesList/check scraping status
Campaigns
POST/campaignsLaunch a DM campaign
GET/campaignsList campaigns
GET/campaigns/analyticsGet campaign analytics
Conversations
GET/conversationsFetch conversations
POST/dm/sendSend a direct message
CRM
GET/crm/conversationsGet CRM conversations by tag
PATCH/crm/updateUpdate CRM data
Scheduled Tweets
POST/scheduled-tweetsSchedule a tweet
GET/scheduled-tweetsList scheduled tweets
DELETE/scheduled-tweetsCancel scheduled tweet

Quick Start

1. Generate an API key from your Settings page

2. Make your first API call:

bash
curl -H "X-API-Key: YOUR_API_KEY" \
  https://app.scrapely.co/api/v1/accounts

OpenAPI Specification

Download our OpenAPI spec to generate typed clients for any language:

bash
# Generate TypeScript client
npx openapi-typescript-codegen --input https://app.scrapely.co/openapi.yaml --output ./api

# Generate Python client
pip install openapi-python-client
openapi-python-client generate --url https://app.scrapely.co/openapi.yaml

# Import into Postman
# File -> Import -> Link -> https://app.scrapely.co/openapi.yaml

Authentication

All API requests require authentication using an API key. Generate API keys from your Settings page.

X-API-Key Header (Recommended)

bash
curl -H "X-API-Key: sk_live_your_api_key" \
  https://app.scrapely.co/api/v1/accounts

Authorization Bearer Header

bash
curl -H "Authorization: Bearer sk_live_your_api_key" \
  https://app.scrapely.co/api/v1/accounts
Keep your API key secret!

Never expose your API key in client-side code or public repositories.


List Accounts

GET/accountsList your connected Twitter accounts

Returns a list of all active Twitter accounts. Use the account id when sending DMs.

Request

bash
curl -H "X-API-Key: YOUR_API_KEY" \
  https://app.scrapely.co/api/v1/accounts

Response

json
{
  "accounts": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "handle": "yourhandle",
      "name": "Your Name",
      "profile_image_url": "https://pbs.twimg.com/...",
      "is_active": true,
      "is_verified": true,
      "dms_sent": 1250,
      "created_at": "2024-01-15T10:30:00Z",
      "cookies": [
        { "name": "auth_token", "value": "abc123...", "domain": ".x.com" },
        { "name": "ct0", "value": "xyz789...", "domain": ".x.com" }
      ],
      "proxy": "161.77.187.46:12323",
      "proxy_auth": "username:password",
      "is_paused": false,
      "followups_paused": false,
      "warmup_paused": false,
      "ai_setter_enabled": true
    }
  ]
}

Response Fields

FieldTypeDescription
is_pausedbooleanWhether DM sending is paused for this account
followups_pausedbooleanWhether follow-up messages are paused
warmup_pausedbooleanWhether account warmup is paused
ai_setter_enabledbooleanWhether AI setter is enabled for this account

Add Account

POST/accountsAdd a new Twitter account

Add a new Twitter account to your workspace. Requires cookies exported from your browser and a proxy configuration.

Request Body

ParameterTypeRequiredDescription
handlestringRequiredTwitter handle (with or without @)
cookiesarrayRequiredArray of cookie objects (Chrome export format)
proxystringRequiredProxy URL (e.g., http://proxy.example.com:8080)
proxy_authstringRequiredProxy authentication (username:password)
xchat_pinstringRequiredX chat PIN code

Request

bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "handle": "myhandle",
    "cookies": [
      {"name": "ct0", "value": "abc123...", "domain": ".twitter.com"},
      {"name": "auth_token", "value": "xyz789...", "domain": ".twitter.com"}
    ],
    "proxy": "http://proxy.example.com:8080",
    "proxy_auth": "username:password",
    "xchat_pin": "123456"
  }' \
  https://app.scrapely.co/api/v1/accounts

Response

json
{
  "success": true,
  "message": "Account created successfully",
  "account": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "handle": "myhandle",
    "is_active": true,
    "created_at": "2024-01-15T10:30:00Z",
    "is_new": true
  }
}
Cookie Requirements

Cookies must include at minimum ct0 and auth_token. Use a browser extension like "EditThisCookie" to export cookies from Twitter.


Remove Account

DELETE/accountsRemove a Twitter account

Remove a Twitter account from your workspace. You can identify the account by either its UUID or Twitter handle.

Request Body

ParameterTypeRequiredDescription
account_idstringRequired*The account UUID to remove
handlestringRequired*Twitter handle to remove (with or without @)

*Either account_id or handle is required.

Request (by ID)

bash
curl -X DELETE \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "550e8400-e29b-41d4-a716-446655440000"
  }' \
  https://app.scrapely.co/api/v1/accounts

Request (by Handle)

bash
curl -X DELETE \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "handle": "myhandle"
  }' \
  https://app.scrapely.co/api/v1/accounts

Response

json
{
  "success": true,
  "message": "Account removed successfully",
  "account": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "handle": "myhandle"
  }
}
Warning: This action is permanent

Removing an account will permanently delete it from your workspace. All associated data including DM history will be retained, but the account will no longer be available for sending messages.


Update Cookies

PUT/accounts/cookiesUpdate cookies for an existing account

Update cookies for an existing account when the session expires. This will also reactivate the account if it was disabled.

Request Body

ParameterTypeRequiredDescription
account_idstringRequiredThe account UUID
cookiesarrayRequiredArray of cookie objects

Request

bash
curl -X PUT \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "550e8400-e29b-41d4-a716-446655440000",
    "cookies": [
      {"name": "ct0", "value": "new_value...", "domain": ".twitter.com"},
      {"name": "auth_token", "value": "new_token...", "domain": ".twitter.com"}
    ]
  }' \
  https://app.scrapely.co/api/v1/accounts/cookies

Response

json
{
  "success": true,
  "message": "Cookies updated successfully",
  "account": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "handle": "myhandle",
    "is_active": true
  }
}

Extract Cookies

POST/get-cookiesQueue a cookie extraction job

Submit account credentials and receive the session cookies for a Twitter account. Jobs are processed sequentially. Processing typically takes 1-2 minutes.

How It Works

  1. Submit credentials and proxy configuration
  2. Receive a job_id immediately
  3. Poll /get-cookies/status?job_id=xxx to check progress
  4. When completed, retrieve the extracted cookies

Request Body

ParameterTypeRequiredDescription
usernamestringRequiredTwitter username/handle
passwordstringRequiredAccount password
two_fa_keystringRequiredTOTP 2FA secret (16 char alphanumeric)
proxystringRequiredProxy URL (e.g., http://proxy.example.com:8080)
proxy_authstringRequiredProxy authentication (username:password)
xchat_pinstringRequiredX Chat PIN to set (4-6 digits)

Request

bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "myhandle",
    "password": "mypassword123",
    "two_fa_key": "ABCD1234EFGH5678",
    "proxy": "http://proxy.example.com:8080",
    "proxy_auth": "proxyuser:proxypass",
    "xchat_pin": "1234"
  }' \
  https://app.scrapely.co/api/v1/get-cookies

Response

json
{
  "success": true,
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "queued",
  "username": "myhandle",
  "created_at": "2024-01-15T10:30:00Z",
  "message": "Cookie extraction job queued. Poll GET /api/v1/get-cookies/status?job_id=550e8400-... to check progress."
}
Sequential Processing

Jobs are processed one at a time. If there are jobs ahead of yours in the queue, your job will wait. You can submit multiple jobs, but they will be processed sequentially.


Check Extraction Status

GET/get-cookies/statusCheck cookie extraction job status

Poll this endpoint to check the status of a cookie extraction job and retrieve the results when completed.

Query Parameters

ParameterTypeRequiredDescription
job_idstringRequiredThe job UUID from POST /get-cookies

Request

bash
curl -H "X-API-Key: YOUR_API_KEY" \
  "https://app.scrapely.co/api/v1/get-cookies/status?job_id=550e8400-e29b-41d4-a716-446655440000"

Response (Queued)

json
{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "queued",
  "username": "myhandle",
  "created_at": "2024-01-15T10:30:00Z",
  "message": "Job is queued and waiting to be processed"
}

Response (Processing)

json
{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "processing",
  "username": "myhandle",
  "created_at": "2024-01-15T10:30:00Z",
  "started_at": "2024-01-15T10:31:00Z",
  "message": "Job is currently being processed"
}

Response (Completed)

json
{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "completed",
  "username": "myhandle",
  "created_at": "2024-01-15T10:30:00Z",
  "started_at": "2024-01-15T10:31:00Z",
  "completed_at": "2024-01-15T10:32:30Z",
  "message": "Cookie extraction completed successfully",
  "cookies": [
    { "name": "auth_token", "value": "abc123...", "domain": ".x.com" },
    { "name": "ct0", "value": "xyz789...", "domain": ".x.com" }
  ]
}

Response (Failed)

json
{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "failed",
  "username": "myhandle",
  "created_at": "2024-01-15T10:30:00Z",
  "started_at": "2024-01-15T10:31:00Z",
  "completed_at": "2024-01-15T10:32:00Z",
  "message": "Cookie extraction failed",
  "error": "Incorrect password"
}
Status Values
  • queued - Waiting to be processed
  • processing - Currently being processed
  • completed - Cookies extracted (includes cookies array)
  • failed - Extraction failed (includes error message)
Common Failure Reasons
  • Incorrect password
  • Invalid 2FA key
  • Account requires email/phone verification
  • Account blocked by Twitter
  • Proxy connection issues

Create Scraping Source

POST/scraping-sourcesCreate a new lead source by scraping Twitter

Create a lead source by scraping followers and/or following from Twitter accounts. Credits are consumed based on the number of leads scraped.

Request Body

ParameterTypeRequiredDescription
namestringRequiredName for the lead source
sourcesarrayRequiredArray of scraping targets
filtersobjectOptionalFilter configuration to filter scraped leads

Source Object

ParameterTypeDescription
handlestringTwitter handle to scrape
followersbooleanScrape followers
followingbooleanScrape following

All followers/following will be scraped automatically. Credits are deducted as leads are imported.

Filters Object

Apply filters to scraped leads in real-time during the scraping process. Only leads matching your filter criteria will be saved and count against your credits.

ParameterTypeDescription
includeKeywordsarrayArray of keyword groups. Each group is an array of keywords. Leads must match keywords in their bio/description.
excludeKeywordsarrayArray of keyword groups to exclude. Leads matching these keywords will be filtered out.
includeWithinLogicstring"AND" or "OR". Logic within each include keyword group. Default: "AND"
includeBetweenLogicstring"AND" or "OR". Logic between include keyword groups. Default: "OR"
excludeWithinLogicstring"AND" or "OR". Logic within each exclude keyword group. Default: "AND"
excludeBetweenLogicstring"AND" or "OR". Logic between exclude keyword groups. Default: "OR"
locationExcludeKeywordsarrayArray of location keywords to exclude (e.g., country names).
followersobject{ min: number, max: number }. Only keep leads who have this many followers themselves.
followingobject{ min: number, max: number }. Only keep leads who are following this many accounts.
hasWebsitebooleantrue = only leads with website, false = only leads without website, null = no filter.

Request

bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Tech Founders Q1",
    "sources": [
      {
        "handle": "paulg",
        "followers": true
      },
      {
        "handle": "naval",
        "followers": true,
        "following": true
      }
    ],
    "filters": {
      "includeKeywords": [["founder", "ceo"], ["startup"]],
      "includeBetweenLogic": "OR",
      "includeWithinLogic": "AND",
      "excludeKeywords": [["hiring", "recruiter"]],
      "followers": { "min": 100, "max": 50000 },
      "hasWebsite": true
    }
  }' \
  https://app.scrapely.co/api/v1/scraping-sources

Response

json
{
  "success": true,
  "lead_source_id": "uuid-here",
  "name": "Tech Founders Q1",
  "jobs_created": 3,
  "message": "Scraping all followers/following. Credits deducted as leads are imported.",
  "jobs": [
    {
      "id": "job-uuid-1",
      "type": "followers",
      "handle": "paulg",
      "status": "pending"
    },
    {
      "id": "job-uuid-2",
      "type": "followers",
      "handle": "naval",
      "status": "pending"
    },
    {
      "id": "job-uuid-3",
      "type": "following",
      "handle": "naval",
      "status": "pending"
    }
  ]
}

Check Scraping Status

GET/scraping-sourcesList scraping sources or get status

Check the status of your scraping jobs. Pass an id parameter to get detailed status for a specific source.

Query Parameters

ParameterTypeDescription
idstringGet specific source by ID
limitnumberResults per page (default: 20, max: 100)
offsetnumberPagination offset

Request

bash
curl -H "X-API-Key: YOUR_API_KEY" \
  "https://app.scrapely.co/api/v1/scraping-sources?id=uuid-here"

Response

json
{
  "scraping_source": {
    "id": "uuid-here",
    "name": "Tech Founders Q1",
    "status": "processing",
    "leads_imported": 4200,
    "total_leads": 9000,
    "progress": 47,
    "handles": [
      {
        "handle": "paulg",
        "followers": {
          "status": "completed",
          "leads_imported": 5000,
          "max_leads": 5000
        },
        "following": null
      }
    ],
    "created_at": "2024-01-15T10:30:00Z"
  }
}
Status Values
  • pending - Job queued, not started
  • processing - Currently scraping
  • completed - Successfully finished
  • failed - Error occurred

Launch Campaign

POST/campaignsLaunch a DM campaign

Launch a DM campaign targeting leads from your scraping sources. Supports A/B testing with multiple message variants. Maximum 25,000 leads per campaign.

Request Body

ParameterTypeRequiredDescription
namestringRequiredCampaign name
messagestringRequired*Message text (supports {{firstName}})
message_variantsarrayOptionalMessage variants for A/B testing (max 5)
lead_source_idsarrayRequiredLead source IDs to target
account_idsarrayOptionalAccount IDs to send from (defaults to all)
followupsarrayOptionalFollow-up messages
max_leadsnumberOptionalMaximum leads to target (max 25,000)
enable_followbooleanOptionalFollow the lead's profile before DM (default: false)
enable_likebooleanOptionalLike the lead's recent post before DM (default: false)
enable_commentbooleanOptionalComment on the lead's post before DM (default: false)
comment_templatestringOptionalAI personalization template for auto-generated comments

*Either message or message_variants is required.

Request

bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Outreach Campaign Q1",
    "message_variants": [
      {
        "message": "Hey {{firstName}}, I saw your work and wanted to connect!",
        "followups": [
          {"wait_time": 3, "wait_unit": "days", "message": "Just bumping this up!"}
        ]
      },
      {
        "message": "Hi {{firstName}}! Quick question about your business..."
      }
    ],
    "lead_source_ids": ["uuid-1", "uuid-2"],
    "enable_follow": true,
    "enable_like": true,
    "enable_comment": true,
    "comment_template": "Great insights on {{topic}}!"
  }' \
  https://app.scrapely.co/api/v1/campaigns

Response

json
{
  "success": true,
  "campaign_name": "Outreach Campaign Q1",
  "jobs_created": 1500,
  "leads_targeted": 1500,
  "message_variants": 2,
  "accounts_used": 2,
  "distribution": [
    {"account_id": "uuid", "handle": "account1", "jobs": 750},
    {"account_id": "uuid", "handle": "account2", "jobs": 750}
  ]
}

List Campaigns

GET/campaignsList campaigns with basic stats

Request

bash
curl -H "X-API-Key: YOUR_API_KEY" \
  "https://app.scrapely.co/api/v1/campaigns?limit=10"

Response

json
{
  "campaigns": [
    {
      "name": "Outreach Campaign Q1",
      "total": 1500,
      "completed": 1200,
      "pending": 250,
      "failed": 50,
      "progress": 80
    }
  ],
  "pagination": {
    "limit": 10,
    "offset": 0,
    "count": 1,
    "total": 5
  }
}

Campaign Analytics

GET/campaigns/analyticsGet detailed campaign analytics

Get detailed analytics including reply rates, sentiment analysis, and per-variant A/B testing statistics. Returns the same data structure as the dashboard UI.

Query Parameters

ParameterTypeDescription
campaign_namestringFilter to specific campaign
account_idstringFilter to specific account

Request

bash
curl -H "X-API-Key: YOUR_API_KEY" \
  https://app.scrapely.co/api/v1/campaigns/analytics

Response

json
{
  "accounts": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "handle": "myhandle",
      "name": "My Account",
      "profile_image_url": "https://pbs.twimg.com/...",
      "is_paused": false,
      "dms_sent": 1500,
      "dms_sent_24hrs": 45,
      "responses": 180,
      "response_rate": 12.0,
      "pending_count": 250,
      "sentiment": {
        "positive": 120,
        "negative": 15,
        "neutral": 45
      }
    }
  ],
  "campaigns": [
    {
      "account_id": "550e8400-e29b-41d4-a716-446655440000",
      "account_handle": "myhandle",
      "campaign_name": "Outreach Q1",
      "total": 1500,
      "completed": 1200,
      "pending": 250,
      "failed": 50,
      "remaining": 250,
      "progress": 80,
      "reply_count": 150,
      "response_rate": 12.5
    }
  ],
  "campaignSentimentStats": [
    {
      "campaign_name": "Outreach Q1",
      "account_id": "550e8400-e29b-41d4-a716-446655440000",
      "sentiment": {
        "positive": 100,
        "negative": 12,
        "neutral": 38,
        "total": 150
      },
      "reply_count": 150
    }
  ],
  "campaignVariantStats": [
    {
      "campaign_name": "Outreach Q1",
      "account_id": "550e8400-e29b-41d4-a716-446655440000",
      "variants": [
        {
          "message": "Hey {{firstName}}, loved your recent post...",
          "sent": 600,
          "replied": 90,
          "reply_rate": 15.0
        },
        {
          "message": "Hi {{firstName}}, saw you're building...",
          "sent": 600,
          "replied": 60,
          "reply_rate": 10.0
        }
      ]
    }
  ],
  "totals": {
    "dms_sent": 1500,
    "responses": 180,
    "response_rate": 12.0,
    "positive": 120,
    "negative": 15,
    "neutral": 45
  }
}

Fetch Conversations

GET/conversationsFetch DM conversations

Returns conversations with lead info. Pass a conversation_id to get a single conversation with all messages and complete lead data.

Query Parameters

ParameterTypeRequiredDescription
conversation_idstringOptionalGet single conversation with all messages & lead info
account_idstringOptionalFilter by Twitter account
handlestringOptionalFilter by receiver handle
limitnumberOptionalResults per page (max 100)
cursorstringOptionalPagination cursor (recommended)
include_messagesbooleanOptionalInclude full message history (for list view)
Cursor Pagination (Recommended)

Use cursor instead of offset for reliable pagination. The next_cursor in the response can be passed as the cursor parameter.

List Conversations

bash
curl -H "X-API-Key: YOUR_API_KEY" \
  "https://app.scrapely.co/api/v1/conversations?limit=10"

List Response

json
{
  "conversations": [
    {
      "conversation_id": "123456789-987654321",
      "account_handle": "yourhandle",
      "receiver": {
        "screen_name": "prospect",
        "name": "John Doe",
        "bio": "Founder @ Startup",
        "website": "https://example.com",
        "location": "San Francisco",
        "followers_count": 5000
      },
      "last_message": {
        "text": "Thanks for reaching out!",
        "time": 1709234567000,
        "is_sent": false
      },
      "is_unread": true
    }
  ],
  "pagination": {
    "limit": 10,
    "count": 10,
    "has_more": true
  },
  "next_cursor": "eyJ0IjoxNzA5MjM0NTY3MDAwLCJpIjoiYWJjMTIzIn0"
}

Get Single Conversation

Pass conversation_id to get full details:

bash
curl -H "X-API-Key: YOUR_API_KEY" \
  "https://app.scrapely.co/api/v1/conversations?conversation_id=123456789-987654321"

Single Conversation Response

json
{
  "conversation": {
    "id": "uuid-here",
    "conversation_id": "123456789-987654321",
    "account_handle": "yourhandle",
    "lead": {
      "user_id": "987654321",
      "screen_name": "prospect",
      "name": "John Doe",
      "profile_image_url": "https://pbs.twimg.com/...",
      "profile_banner_url": "https://pbs.twimg.com/...",
      "bio": "Founder @ Startup | Building cool things",
      "location": "San Francisco, CA",
      "website": "https://example.com",
      "followers_count": 5000,
      "following_count": 1200,
      "verified": false
    },
    "crm": {
      "notes": "Interested in enterprise plan",
      "deal_value": 5000.00,
      "deal_currency": "USD"
    },
    "stats": {
      "message_count": 8,
      "is_unread": false,
      "last_message_time": 1709234567000,
      "last_message_text": "Sounds great, let's schedule a call!",
      "last_message_is_sent": false
    },
    "messages": [
      {
        "text": "Hey! Saw your work on...",
        "time": 1709200000000,
        "sender": "123456789",
        "isSent": true
      },
      {
        "text": "Thanks for reaching out!",
        "time": 1709210000000,
        "sender": "987654321",
        "isSent": false
      }
    ],
    "created_at": "2024-02-28T10:00:00.000Z",
    "updated_at": "2024-02-28T12:30:00.000Z"
  }
}

Send DM

POST/dm/sendSend a direct message

Send a direct message to an existing conversation.

Request Body

ParameterTypeRequiredDescription
conversation_idstringRequiredThe conversation ID
messagestringRequiredMessage text (max 10,000 chars)
account_idstringRequiredTwitter account ID to send from

Request

bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "conversation_id": "123456789-987654321",
    "message": "Hey! Just following up.",
    "account_id": "550e8400-e29b-41d4-a716-446655440000"
  }' \
  https://app.scrapely.co/api/v1/dm/send

Response

json
{
  "success": true,
  "message_id": "1234567890123456789",
  "conversation_id": "123456789-987654321",
  "account_handle": "yourhandle"
}

Get CRM Conversations

GET/crm/conversationsGet conversations organized by CRM tags

Fetch conversations organized by CRM tags like "interested", "negative", "booked", etc.

Query Parameters

ParameterTypeDescription
tagstringFilter to specific tag
limitnumberConversations per tag (default: 20, max: 100)
include_messagesbooleanInclude full message history

Request

bash
curl -H "X-API-Key: YOUR_API_KEY" \
  https://app.scrapely.co/api/v1/crm/conversations

Response

json
{
  "columns": {
    "interested_reply": {
      "conversations": [
        {
          "id": "conv-key",
          "conversation_id": "123456-789012",
          "account_handle": "myhandle",
          "tag": "interested_reply",
          "receiver": {
            "screen_name": "lead_handle",
            "name": "Interested Lead",
            "bio": "CEO at...",
            "followers_count": 10000
          },
          "crm": {
            "notes": "Interested in demo",
            "deal_value": 5000,
            "deal_currency": "USD"
          },
          "last_message": {
            "text": "Yes, I'd love to learn more!",
            "time": "2024-01-15T14:30:00Z"
          }
        }
      ],
      "count": 1
    },
    "negative_reply": {
      "conversations": [],
      "count": 0
    }
  },
  "custom_tags": [
    {"id": "uuid", "name": "Hot Lead", "color": "#ff0000", "key": "custom_uuid"}
  ],
  "base_tags": [
    "unread", "interested_reply", "negative_reply", "neutral_reply",
    "engaged", "calendlyd", "booked", "not_interested", "not_qualified"
  ]
}

Update CRM Data

PATCH/crm/updateUpdate notes, deal value, or tags

Update CRM data for a conversation including notes, deal value, and tags.

Request Body

ParameterTypeRequiredDescription
conversation_idstringRequiredThe conversation ID
account_handlestringRequiredThe account handle
notesstringOptionalNotes for the conversation
deal_valuenumberOptionalDeal value
deal_currencystringOptionalCurrency code (default: USD)
tagstringOptionalTag to set (null to remove)

Request

bash
curl -X PATCH \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "conversation_id": "123456-789012",
    "account_handle": "myhandle",
    "notes": "Interested in enterprise plan. Follow up Monday.",
    "deal_value": 10000,
    "deal_currency": "USD",
    "tag": "interested_reply"
  }' \
  https://app.scrapely.co/api/v1/crm/update

Response

json
{
  "success": true,
  "updated": {
    "conversation_id": "123456-789012",
    "account_handle": "myhandle",
    "notes": "Interested in enterprise plan. Follow up Monday.",
    "deal_value": 10000,
    "deal_currency": "USD",
    "tag": "interested_reply"
  }
}

Schedule Tweet

POST/scheduled-tweetsSchedule a tweet to be posted at a specific time

Schedule a tweet to be automatically posted from one of your accounts at a specified time. The tweet will be posted by the background worker when the scheduled time arrives.

Request Body

ParameterTypeRequiredDescription
account_idstringRequiredThe account UUID to post from
tweet_textstringRequiredThe tweet content (max 280 characters)
scheduled_atstringRequiredISO 8601 timestamp for when to post (must be in the future)

Request

bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "550e8400-e29b-41d4-a716-446655440000",
    "tweet_text": "Just launched a new feature! Check it out",
    "scheduled_at": "2024-03-20T15:00:00Z"
  }' \
  https://app.scrapely.co/api/v1/scheduled-tweets

Response

json
{
  "success": true,
  "message": "Tweet scheduled successfully",
  "scheduled_tweet": {
    "id": "7f3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
    "account_id": "550e8400-e29b-41d4-a716-446655440000",
    "account_handle": "myhandle",
    "tweet_text": "Just launched a new feature! Check it out",
    "scheduled_at": "2024-03-20T15:00:00.000Z",
    "status": "pending",
    "created_at": "2024-03-15T10:30:00.000Z"
  }
}
Tweet Status
  • pending - Waiting to be posted
  • posted - Successfully posted
  • failed - Failed to post (check error_message)

List Scheduled Tweets

GET/scheduled-tweetsList all scheduled tweets

Retrieve a list of scheduled tweets for your accounts. Filter by account, status, or use pagination.

Query Parameters

ParameterTypeDescription
account_idstringFilter by specific account UUID
statusstringFilter by status: pending, posted, failed
limitnumberMax results (default: 50, max: 100)
offsetnumberPagination offset

Request

bash
curl -H "X-API-Key: YOUR_API_KEY" \
  "https://app.scrapely.co/api/v1/scheduled-tweets?status=pending&limit=10"

Response

json
{
  "scheduled_tweets": [
    {
      "id": "7f3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
      "account_id": "550e8400-e29b-41d4-a716-446655440000",
      "account_handle": "myhandle",
      "account_name": "My Account",
      "account_image": "https://pbs.twimg.com/...",
      "tweet_text": "Just launched a new feature!",
      "scheduled_at": "2024-03-20T15:00:00.000Z",
      "status": "pending",
      "posted_at": null,
      "error_message": null,
      "created_at": "2024-03-15T10:30:00.000Z"
    }
  ],
  "pagination": {
    "limit": 10,
    "offset": 0,
    "count": 1,
    "total": 5
  }
}

Cancel Scheduled Tweet

DELETE/scheduled-tweetsCancel a pending scheduled tweet

Cancel a scheduled tweet before it gets posted. Only tweets with status "pending" can be cancelled.

Request Body

ParameterTypeRequiredDescription
tweet_idstringRequiredThe scheduled tweet UUID to cancel

Request

bash
curl -X DELETE \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tweet_id": "7f3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c"
  }' \
  https://app.scrapely.co/api/v1/scheduled-tweets

Response

json
{
  "success": true,
  "message": "Scheduled tweet cancelled",
  "tweet_id": "7f3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c"
}
Note

You can only cancel tweets with status "pending". Once a tweet has been posted or failed, it cannot be cancelled.


Error Handling

The API uses conventional HTTP response codes.

HTTP Status Codes

CodeDescription
200Success
400Bad Request - Invalid parameters
401Unauthorized - Invalid API key
403Forbidden - Subscription not active
429Rate Limited - Too many requests
500Internal Server Error

Error Response Format

json
{
  "error": "Unauthorized",
  "message": "Invalid API key"
}

Rate Limits

API requests are rate limited to ensure fair usage.

60 requests
per minute per API key

Response Headers

Every response includes these headers:

text
X-Request-ID: req_m1abc123def456
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1709234567
Request IDs

Every response includes an X-Request-ID header. Include this ID when contacting support for faster debugging.

Rate Limit Error

json
{
  "error": "Rate limited",
  "message": "Too many requests. Please try again later.",
  "retry_after": 45
}
Best Practices
  • Implement exponential backoff when retrying
  • Cache responses when possible
  • Use webhooks for real-time updates

Webhooks

Webhooks allow you to receive real-time notifications when events occur in your Scrapely account. Configure your webhook URL in Settings to start receiving events.

Webhook Events

EventDescription
new_replyA prospect replied to your DM
account_pausedA Twitter account was disconnected or paused
leads_exhaustedA campaign has run out of leads to contact

Webhook Payload Format

All webhook payloads follow this structure:

json
{
  "event": "event_type",
  "timestamp": "2024-02-28T12:00:00.000Z",
  "data": {
    // Event-specific data
  }
}

new_reply Event

Sent when a prospect replies to your DM:

json
{
  "event": "new_reply",
  "timestamp": "2024-02-28T12:00:00.000Z",
  "data": {
    "conversation_id": "123456789-987654321",
    "account_handle": "yourhandle",
    "receiver": {
      "screen_name": "prospect",
      "name": "John Doe",
      "profile_image_url": "https://pbs.twimg.com/..."
    },
    "message": {
      "id": "1234567890123456789",
      "text": "Hey! I'm interested, let's chat.",
      "created_at": "2024-02-28T12:00:00.000Z"
    }
  }
}

account_paused Event

Sent when a Twitter account is disconnected:

json
{
  "event": "account_paused",
  "timestamp": "2024-02-28T12:00:00.000Z",
  "data": {
    "account_id": "550e8400-e29b-41d4-a716-446655440000",
    "account_handle": "yourhandle",
    "reason": "Session expired or account disconnected"
  }
}

leads_exhausted Event

Sent when a campaign runs out of leads:

json
{
  "event": "leads_exhausted",
  "timestamp": "2024-02-28T12:00:00.000Z",
  "data": {
    "campaign_id": "camp_abc123",
    "campaign_name": "SaaS Founders Outreach",
    "account_handle": "yourhandle",
    "total_sent": 500
  }
}

Responding to Webhooks

Your endpoint should return a 200 status code within 30 seconds. If we don't receive a successful response, we'll retry up to 3 times with exponential backoff.

Verifying Webhooks

Validate the payload structure before processing to ensure it came from Scrapely.