API Reference
Upscale APIs for personalised LinkedIn outreach. Integrate message generation and retrieval with your tools.
Introduction
The Upscale API lets you integrate personalised LinkedIn message generation with your systems. Send prospects, receive generated messages, and get notified when processing is complete.
Base URL
https://app.upscaleoutreach.com/api/v2Authentication
Send your API key in the request header and use JSON for the request body:
Api-Key: YOUR_API_KEY
Content-Type: application/jsonYou can find your API keys in your account settings.
Errors
The API returns standard HTTP status codes with JSON response bodies. Below are the main scenarios and example responses.
| Status Code | Scenario | Response Body |
|---|---|---|
| 401 Unauthorized | Invalid API key | {"error": "Unauthorized: Invalid API key"} |
| 401 Unauthorized | Revoked API key | {"error": "Unauthorized: API key has been revoked"} |
| 402 Payment Required | Insufficient credits | {"error": "Not enough credits remaining to complete this request. Please upgrade your plan or purchase a bundle."} |
| 422 Unprocessable Entity | Single validation error | {"error": "message_sequence must be an array"} |
| 422 Unprocessable Entity | Multiple validation errors | {"error": "automation_tool_customer_id is required but was missing or blank proposition_company_url must be a valid HTTP or HTTPS URL lead_data[0].first_name is required but was missing or blank lead_data[1].lead_company is required but was missing or blank"} |
| 422 Unprocessable Entity | Invalid URL format | {"error": "proposition_company_url must be a valid URL"} |
| 422 Unprocessable Entity | Empty lead data | {"error": "lead_data must contain at least one lead"} |
Formatted JSON examples
Invalid API key (401):
{
"error": "Unauthorized: Invalid API key"
}Revoked API key (401):
{
"error": "Unauthorized: API key has been revoked"
}Insufficient credits (402):
{
"error": "Not enough credits remaining to complete this request. Please upgrade your plan or purchase a bundle."
}Validation error - single (422):
{
"error": "message_sequence must be an array"
}Validation error - multiple (422):
{
"error": "automation_tool_customer_id is required but was missing or blank proposition_company_url must be a valid HTTP or HTTPS URL lead_data[0].first_name is required but was missing or blank lead_data[1].lead_company is required but was missing or blank"
}Request Message Generation API
Submit a list of leads and your proposition details to request personalised LinkedIn messages. Provide a completion notification URL to receive a webhook when generation is finished.
Endpoint
| Method | Path |
|---|---|
| POST | /request_message_generation |
Request
Request parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| All fields are mandatory except lead_specified_url and lead_company_website_url on each lead. | |||
| completion_notification_url | string (URL) | Yes | Webhook URL to receive notification when message generation is complete |
| automation_tool_customer_id | string | Yes | Your internal customer/account identifier |
| automation_tool_campaign_id | string | Yes | Your internal campaign identifier |
| proposition_company_name | string | Yes | The name of the campaign proposition company (for personalization) |
| proposition_company_url | string (URL) | Yes | The website of that company (must be valid HTTP/HTTPS) |
| message_sequence | array of strings | Yes | Array of message types to generate. Allowed values: connection_request, first_follow_up, share_material, hiring_activity. Values coming soon: industry_insight, proposition_summary, breakup, linkedin_post, re-engagement, youtube_content, trustpilot_reviews |
| tone_preference | string | No | Optional. One of: formal, normal, or casual only. Default is normal if omitted. |
| lead_data | array | Yes | Array of lead objects (minimum 1 required) |
Lead data object parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| automation_tool_lead_id | string | Yes | Your internal lead/prospect identifier |
| lead_linkedin | string (URL) | Yes | LinkedIn profile URL of the prospect |
| lead_company | string | Yes | Company name where the prospect works |
| first_name | string | Yes | Prospect's first name |
| last_name | string | Yes | Prospect's last name |
| lead_company_website_url | string (URL) | No | Company website URL (optional) |
| lead_specified_url | string (URL) | No | Specific URL for research (optional). If provided, this URL is used for research instead of lead_company_website_url. When both are given, lead_specified_url takes precedence over any website URL. |
Notes
- The
message_sequencearray determines which message types will be generated for each prospect. - The
completion_notification_urlis required so you receive webhook notifications when generation completes. - All
lead_dataentries must include the required fields listed above. - The API returns a
secure_request_idthat you use with the Retrieve Messages API to fetch the generated messages.
Example request (JSON body)
{
"completion_notification_url": "https://your-webhook-endpoint.com/webhook",
"automation_tool_customer_id": "customer_12345",
"automation_tool_campaign_id": "campaign_67890",
"proposition_company_name": "Acme Corporation",
"proposition_company_url": "https://www.acmecorp.com",
"message_sequence": ["connection_request", "first_follow_up"],
"tone_preference": "formal",
"lead_data": [
{
"automation_tool_lead_id": "lead_001",
"lead_linkedin": "https://linkedin.com/in/john-doe",
"lead_company": "Tech Solutions Inc",
"first_name": "John",
"last_name": "Doe",
"lead_company_website_url": "https://www.techsolutions.com",
"lead_specified_url": null
},
{
"automation_tool_lead_id": "lead_002",
"lead_linkedin": "https://linkedin.com/in/jane-smith",
"lead_company": "Digital Innovations LLC",
"first_name": "Jane",
"last_name": "Smith",
"lead_company_website_url": "https://www.digitalinnovations.com",
"lead_specified_url": null
}
]
}Complete cURL example
curl --location 'https://app.upscaleoutreach.com/api/v2/request_message_generation' \
--header 'Api-Key: your_api_key_here' \
--header 'Content-Type: application/json' \
--data '{
"completion_notification_url": "https://your-webhook-endpoint.com/webhook",
"automation_tool_customer_id": "customer_12345",
"automation_tool_campaign_id": "campaign_67890",
"proposition_company_name": "Acme Corporation",
"proposition_company_url": "https://www.acmecorp.com",
"message_sequence": ["connection_request", "first_follow_up"],
"tone_preference": "casual",
"lead_data": [
{
"automation_tool_lead_id": "lead_001",
"lead_linkedin": "https://linkedin.com/in/john-doe",
"lead_company": "Tech Solutions Inc",
"first_name": "John",
"last_name": "Doe",
"lead_company_website_url": "https://www.techsolutions.com",
"lead_specified_url": null
},
{
"automation_tool_lead_id": "lead_002",
"lead_linkedin": "https://linkedin.com/in/jane-smith",
"lead_company": "Digital Innovations LLC",
"first_name": "Jane",
"last_name": "Smith",
"lead_company_website_url": "https://www.digitalinnovations.com",
"lead_specified_url": null
}
]
}'Example with fetch (JavaScript)
fetch('https://app.upscaleoutreach.com/api/v2/request_message_generation', {
method: 'POST',
headers: {
'Api-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
completion_notification_url: 'https://your-webhook-endpoint.com/webhook',
automation_tool_customer_id: 'customer_12345',
automation_tool_campaign_id: 'campaign_67890',
proposition_company_name: 'Acme Corporation',
proposition_company_url: 'https://www.acmecorp.com',
message_sequence: ['connection_request', 'first_follow_up'],
tone_preference: 'formal',
lead_data: [ /* ... */ ]
})
})Response
On success (200), the response includes message and secure_request_id. Use secure_request_id to retrieve the generated messages (see Retrieve Messages API) and to identify the request in completion webhook payloads.
{
"message": "Success",
"secure_request_id": "3d68ae3b-5957-454d-be1c-8731a4f877f6"
}Retrieve Messages API
Fetch the generated messages for a request. Send the secure_request_id returned from the Request Message Generation API to retrieve all messages (and metadata) for that request.
Endpoint
| Method | Path |
|---|---|
| GET | /retrieve_messages |
Headers: Api-Key: your_api_key_here, Content-Type: application/json
Request
Request parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| request_message_generation_secure_request_id | string (UUID) | Yes | The secure_request_id returned from the Request Message Generation API (/request_message_generation) |
Notes
- The
request_message_generation_secure_request_idis thesecure_request_idvalue returned in the success response from the Request Message Generation API. - The Api-Key header must contain a valid, non-revoked API key.
- The response returns generated messages for all prospects associated with that original message generation request.
Example request (JSON body)
{
"request_message_generation_secure_request_id": "550e8400-e29b-41d4-a716-446655440000"
}Complete cURL example
curl --location --request GET 'https://app.upscaleoutreach.com/api/v2/retrieve_messages' \
--header 'Api-Key: your_api_key_here' \
--header 'Content-Type: application/json' \
--data '{
"request_message_generation_secure_request_id": "550e8400-e29b-41d4-a716-446655440000"
}'Response
On success (200), the response includes metadata, account, and campaign. The campaign.leads_data array contains one object per lead, with message fields (outreach_message, first_follow_up_message, share_material_message, hiring_activity_message) matching the message_sequence. When a message could not be generated for a prospect, that lead's fields may be null and metadata.failed_messages_count and metadata.failed_messages_reason are populated.
200 OK - Success (all messages generated)
Scenario: All requested messages were successfully generated.
{
"metadata": {
"request_message_generation_api_request_secure_request_id": "550e8400-e29b-41d4-a716-446655440000",
"retrieve_messages_api_request_secure_request_id": "660e8400-e29b-41d4-a716-446655440001",
"requested_messages_count": 5,
"generated_messages_count": 5,
"failed_messages_count": null,
"failed_messages_reason": null
},
"account": {
"automation_tool_customer_id": "customer_12345"
},
"campaign": {
"automation_tool_campaign_id": "campaign_67890",
"message_sequence": ["connection_request", "first_follow_up"],
"leads_data": [
{
"external_prospect_id": "lead_001",
"linkedin": "https://linkedin.com/in/john-doe",
"outreach_message": "Hi John, I noticed your work at Acme Corp and thought you might be interested in learning about our solution that helps companies like yours streamline their operations.",
"first_follow_up_message": "Hi John, following up on my previous message. I'd love to share how we've helped similar companies achieve significant cost savings.",
"share_material_message": null,
"hiring_activity_message": null
},
{
"external_prospect_id": "lead_002",
"linkedin": "https://linkedin.com/in/jane-smith",
"outreach_message": "Hi Jane, I saw your recent post about digital transformation and thought our platform might be relevant to your work.",
"first_follow_up_message": "Hi Jane, I wanted to follow up and see if you'd be open to a brief conversation about how we can help.",
"share_material_message": null,
"hiring_activity_message": null
},
{
"external_prospect_id": "lead_003",
"linkedin": "https://linkedin.com/in/bob-johnson",
"outreach_message": "Hi Bob, I noticed your company's recent expansion and thought you might benefit from our services.",
"first_follow_up_message": "Hi Bob, following up to see if you'd like to learn more about how we can support your growth.",
"share_material_message": null,
"hiring_activity_message": null
}
]
}
}200 OK - Success (some messages failed)
Scenario: Some requested messages failed to generate (e.g. insufficient web presence for research). No credits are deducted for failed prospects.
{
"metadata": {
"request_message_generation_api_request_secure_request_id": "550e8400-e29b-41d4-a716-446655440000",
"retrieve_messages_api_request_secure_request_id": "660e8400-e29b-41d4-a716-446655440001",
"requested_messages_count": 10,
"generated_messages_count": 7,
"failed_messages_count": 3,
"failed_messages_reason": "Some prospects do not have enough available web presence for research (including having limited information on LinkedIn, a website that blocks scrapers, and/or a website that is not indexed by search engines). For these prospects, personalisation is not possible. No credits were deducted for these prospects."
},
"account": {
"automation_tool_customer_id": "customer_12345"
},
"campaign": {
"automation_tool_campaign_id": "campaign_67890",
"message_sequence": ["connection_request", "first_follow_up", "share_material_message"],
"leads_data": [
{
"external_prospect_id": "lead_001",
"linkedin": "https://linkedin.com/in/john-doe",
"outreach_message": "Hi John, I noticed your work at Acme Corp and thought you might be interested in learning about our solution.",
"first_follow_up_message": "Hi John, following up on my previous message about how we can help streamline your operations.",
"share_material_message": "Hi John, I thought you might find this resource helpful for your current projects.",
"hiring_activity_message": null
},
{
"external_prospect_id": "lead_002",
"linkedin": "https://linkedin.com/in/jane-smith",
"outreach_message": "Hi Jane, I saw your recent post about digital transformation and thought our platform might be relevant.",
"first_follow_up_message": "Hi Jane, I wanted to follow up and see if you'd be open to a brief conversation.",
"share_material_message": "Hi Jane, I thought you might find this case study helpful - it covers similar challenges to what you're facing.",
"hiring_activity_message": null
},
{
"external_prospect_id": "lead_003",
"linkedin": null,
"outreach_message": null,
"first_follow_up_message": null,
"share_material_message": null,
"hiring_activity_message": null
},
{
"external_prospect_id": "lead_004",
"linkedin": null,
"outreach_message": null,
"first_follow_up_message": null,
"share_material_message": null,
"hiring_activity_message": null
},
{
"external_prospect_id": "lead_005",
"linkedin": null,
"outreach_message": null,
"first_follow_up_message": null,
"share_material_message": null,
"hiring_activity_message": null
}
]
}
}Error response examples
Validation error (e.g. 422):
{
"error": "request_message_generation_secure_request_id is required but was missing or blank",
"status": "error"
}Unauthorized (401):
{
"error": "Unauthorized: API key has been revoked",
"status": "error"
}Get Sequences API
Retrieve available message sequences (and their types) that can be used in the Request Message Generation API. Show these sequences to your users to help them choose the best sequence for their campaign.
Each sequence is associated with a role, industry, geography, and objective - any of which can be used by the user to choose which sequence to use.
These sequences are generated by Upscale based on best practices for LinkedIn outreach - and what we are seeing work best. You can also customise a sequence to your own needs; the Request Message Generation API only needs the list of all message types you want to use in the campaign.
Endpoint
| Method | Path |
|---|---|
| GET | /get_sequences (this is a placeholder - details to be confirmed) |
Headers: Api-Key: your_api_key_here, Content-Type: application/json
Request
Request parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| (placeholder) | - | - | Request parameters to be documented. |
Notes
- Placeholder: request notes and example to be added.
Example request
curl -X GET "https://app.upscaleoutreach.com/api/v2/get_sequences" \
-H "Api-Key: your_api_key_here" \
-H "Content-Type: application/json"Response
On success (200), the response returns the list of available sequences. Placeholder structure below - to be updated with actual fields.
200 OK - Success
{
"sequences": [
{
"id": "placeholder",
"name": "Placeholder sequence",
"message_types": ["connection_request", "first_follow_up"],
"role": "sales",
"industry": "technology",
"geography": "north_america",
"objective": "demonstrate expertise"
}
]
}Error response examples
Unauthorized (401):
{
"error": "Unauthorized: API key invalid or revoked",
"status": "error"
}Account API
Check your account status at any time. The endpoint responds with quota levels and current usage (e.g. message credits). Usage typically resets on a recurring basis. This is a placeholder - details to be added.
Endpoint
| Method | Path |
|---|---|
| GET | /account (this is a placeholder - details to be confirmed) |
Headers: Api-Key: your_api_key_here, Content-Type: application/json
Request
Request parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| (none) | - | - | No request body; authentication via Api-Key header. |
Notes
- Placeholder: request notes and example to be added.
Example request
curl -X GET "https://app.upscaleoutreach.com/api/v2/account" \
-H "Api-Key: your_api_key_here" \
-H "Content-Type: application/json"Response
On success (200), the response returns account details including quota and usage. Placeholder structure below - to be updated with actual fields.
200 OK - Success
{
"created_at": "2024-01-15T10:00:00Z",
"plan_name": "Placeholder plan",
"monthly_credits": 0,
"monthly_allowance": 1000
}Error response examples
Unauthorized (401):
{
"error": "Unauthorized: API key invalid or revoked",
"status": "error"
}Webhooks
When you request message generation, you can provide a URL to receive a notification as soon as the batch is finished. No separate webhook registration is required.
Required: Webhook secret
You must have generated your webhook secret in your account (next to your API key) in order to receive the completion notification. Without it, the webhook will not be sent.
Completion notification
Prerequisite: Pass completion_notification_url in your Request Message Generation API call. That URL receives a single POST request when the batch is done.
As soon as the final message is generated from the requested batch, the notification is sent to the provided URL. Use the payload to reconcile requested_messages_count vs generated_messages_count and to look up the batch via secure_request_id (e.g. with the Retrieve Messages API).
Example webhook payload
The request body is JSON with the following fields:
| Field | Type | Description |
|---|---|---|
| secure_request_id | string | Unique identifier for the message generation request; use with Retrieve Messages API |
| status | string | Status of the batch (e.g. complete) |
| completed_at | string (ISO 8601) | Timestamp when generation completed (UTC) |
| requested_messages_count | integer | Total number of messages requested in the batch |
| generated_messages_count | integer | Number of messages successfully generated |
{
"secure_request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "complete",
"completed_at": "2024-02-08T11:30:45Z",
"requested_messages_count": 12,
"generated_messages_count": 12
}Archived documentation
The following APIs and webhook are archived. They remain available for reference and existing integrations.
- Generate Messages API- Load prospects and request message generation.
- Retrieve Generated Messages API- Retrieve generated messages.
- Completion Notification Webhook- Notifies when message generation is complete.