Skip to content
API

Messages & notifications

Direct messages, conversations, and dashboard notifications.

Direct messages between Scrape.ly users, and the dashboard notification center. Paths are relative to https://api.scrape.ly.

All messaging routes require your user API key; run tokens are rejected with 403 insufficient-permissions.

Conversations

A conversation is a thread between two users. Every new conversation starts as pending. The recipient accepts or rejects it; only after acceptance can either side reply.

Rules for starting a conversation:

  • Your profile must be public (403 profile-not-public).
  • You can't message yourself (403 forbidden).
  • If you already have a pending or accepted conversation with that user, you get 409 conversation-exists. A rejected conversation doesn't block a new one.
  • You can start at most 5 conversations per 24 hours (429 rate-limited).
  • Message bodies are at most 10,000 characters and pass a profanity filter.

Sending (starting a conversation or replying) is also limited to 10 requests per minute per user (429 rate-limit-exceeded).

Start a conversation

POST/v2/users/{username}/messages

Sends the first message to a user, identified by their Scrape.ly username, and creates a pending conversation. The recipient gets a dashboard notification.

.bash
curl -X POST "https://api.scrape.ly/v2/users/janedoe/messages" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "body": "Hi! I have a question about your Actor" }'

201 response:

.json
{
  "data": {
    "id": "conv-uuid",
    "status": "pending",
    "initialMessage": {
      "id": "msg-uuid",
      "body": "Hi! I have a question about your Actor",
      "senderId": "uSeRiDeXaMpLe123",
      "senderUsername": "acme",
      "createdAt": "2026-08-14T16:00:00.000Z"
    }
  }
}

Find a conversation with a user

GET/v2/conversations/with/{username}

Returns your conversation with that user if one exists that isn't rejected and that you haven't deleted from your view. Otherwise returns { "data": null }. Unknown usernames return 404 user-not-found.

.json
{
  "data": {
    "id": "conv-uuid",
    "status": "accepted",
    "isInitiator": true,
    "otherUser": { "id": "uSeRiDeXaMpLe456", "username": "janedoe", "imageUrl": null },
    "createdAt": "2026-08-14T16:00:00.000Z",
    "updatedAt": "2026-08-14T16:05:00.000Z"
  }
}
GET/v2/conversations/with/janedoe

List conversations

GET/v2/user/conversations
Query paramTypeDefaultDescription
statusstring—pending, accepted, or rejected.
limitnumber20Page size, max 100.
offsetnumber0Pagination offset.

Conversations you deleted from your view are omitted.

curl "https://api.scrape.ly/v2/user/conversations?limit=20" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"
GET/v2/user/conversations

Get a conversation

GET/v2/conversations/{conversationId}

Returns the same fields as Find a conversation with a user, plus closedBy ({ "id", "username" }, or null if the conversation is open). Conversations you aren't part of return 403 forbidden; unknown conversations and ones you deleted from your view return 404 conversation-not-found.

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

List messages

GET/v2/conversations/{conversationId}/messages

Message history, oldest first. limit defaults to 50 (max 100), offset to 0. Fetching messages marks the conversation as read for you.

curl "https://api.scrape.ly/v2/conversations/{conversationId}/messages?limit=50&offset=0" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"

Send a message

POST/v2/conversations/{conversationId}/messages

Allowed only on accepted conversations that aren't closed (403 forbidden otherwise). Body: { "body": "..." }.

.bash
curl -X POST "https://api.scrape.ly/v2/conversations/{conversationId}/messages" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "body": "Thanks for the quick reply!" }'

201 response:

.json
{
  "data": {
    "id": "msg-uuid",
    "conversationId": "conv-uuid",
    "senderId": "uSeRiDeXaMpLe123",
    "senderUsername": "acme",
    "body": "Thanks for the quick reply!",
    "createdAt": "2026-08-14T16:05:00.000Z"
  }
}

The other participant gets a dashboard notification unless they turned off dashboard notifications for this conversation.

Accept, reject, or close

PATCH/v2/conversations/{conversationId}/accept
PATCH/v2/conversations/{conversationId}/reject
PATCH/v2/conversations/{conversationId}/close
  • Only the recipient can accept or reject, and only while the conversation is pending.
  • Either participant can close an accepted conversation. After that, nobody can send messages.
  • Acting on a conversation in the wrong state returns 400 invalid-action.
.bash
curl -X PATCH "https://api.scrape.ly/v2/conversations/{conversationId}/accept" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"

Accept returns { "data": { "id": "...", "status": "accepted" } } and notifies the sender. Reject returns status: "rejected". Close returns { "data": { "id": "...", "closedBy": "<userId>" } } and notifies the other participant.

Delete a conversation

DELETE/v2/conversations/{conversationId}

Hides the conversation from your list. The other participant still sees it. Returns { "data": { "success": true } }.

.bash
curl -X DELETE "https://api.scrape.ly/v2/conversations/{conversationId}" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"

Conversation notification settings

GET/v2/conversations/{conversationId}/settings
PUT/v2/conversations/{conversationId}/settings

Your notification settings for one conversation. Defaults: notifyConsole: true, notifyEmail: false.

PUT replaces both values: a field you leave out is saved as false. Always send both.

curl -X PUT "https://api.scrape.ly/v2/conversations/{conversationId}/settings" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "notifyConsole": false, "notifyEmail": false }'

Dashboard notifications

The dashboard notification center (the bell icon). Notification type values include low_balance, plan_expiration, credit_expiration, api_key_created, storage_digest, schedule_failure, actor_auto_test, actor_maintenance_expired, actor_pricing_changed, alert, issue_created, issue_comment, new_message, message_accepted, conversation_closed, and quota_reached. See Notifications for when each is sent.

Errors on these routes use a plain string body, for example { "error": "Failed to fetch notifications" }.

List notifications

GET/v2/console-notifications

Newest first. limit defaults to 50 (max 100), offset to 0. The list is data (an array), with pagination fields at the top level.

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

Scrape.ly keeps roughly your newest 1,000 notifications and trims older ones.

GET/v2/console-notifications

Unread count

GET/v2/console-notifications/unread-count
.json
{ "unreadCount": 3 }

There is no data wrapper.

GET/v2/console-notifications/unread-count

Mark as read

PATCH/v2/console-notifications/read-all
PATCH/v2/console-notifications/{notificationId}/read

Both return { "success": true }.

.bash
curl -X PATCH "https://api.scrape.ly/v2/console-notifications/read-all" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"

Delete all notifications

DELETE/v2/console-notifications

Deletes all of your dashboard notifications, read and unread. Returns { "success": true }.

.bash
curl -X DELETE "https://api.scrape.ly/v2/console-notifications" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"

Account-wide email and dashboard notification preferences live in the Users API.

Errors

StatusTypeMeaning
400invalid-inputMissing or empty message body, or body over 10,000 characters
400invalid-actionConversation is in the wrong state for accept, reject, or close
400profanity-detectedMessage failed the profanity filter
403forbiddenMessaging yourself, not allowed to act on this conversation, or conversation not accepted or closed
403profile-not-publicYour profile must be public to start a conversation
404user-not-found / conversation-not-foundUnknown user or conversation
409conversation-existsA pending or accepted conversation already exists
429rate-limitedMore than 5 new conversations in 24 hours
429rate-limit-exceededMore than 10 sends per minute