Skip to main content

SourceWhale Public API - Overview & Capabilities

An overview of the SourceWhale Public API, including all available endpoints, authentication, and how to get started.

The SourceWhale Public API allows you to programmatically interact with your SourceWhale account, adding contacts, triggering campaigns, querying statistics, and more.

📖 Interactive Documentation
Explore all endpoints and try them live at: https://sourcewhale.app/public-api/swagger

Authentication

Every API request must include your API key in the request header:

API-Key: your_api_key_here

To generate your API key:

  1. Go to your SourceWhale dashboard and click your profile icon in the bottom left corner.

  2. Click Admin, then Settings, then click Generate API Key.

⚠️ Admin access is required to generate an API key.

Base URL

https://sourcewhale.app/public-api

Contacts

Add Contacts: POST /v1/candidates/add

Add one or more contacts to SourceWhale. Optionally enrol them directly into a campaign.

  • candidates (required): Array of contact objects. Each contact can include firstName, lastName, email, phone, socialLinks, and more.

  • campaignId (optional): Enrol contacts into a specific campaign.

  • projectIds (optional): Add contacts to one or more projects.

  • sendImmediately (optional, boolean): If true and a campaignId is provided, outreach sends immediately without review.

  • userEmail (optional, query param): Assign contacts to a specific user by email. Defaults to an admin user.

Response: Returns a url and a list of candidateIds.

Example request:

POST https://sourcewhale.app/public-api/v1/candidates/add{
  "candidates": [
    {
      "firstName": "Jane",
      "lastName": "Smith",
      "email": "jane.smith@example.com",
      "phone": "+447911123456"
    }
  ],
  "campaignId": "your_campaign_id_here"
}

Search Contacts: GET /v1/candidates/search

Look up existing contacts by a specific identifier.

  • key (required): Field to search by: email, phone, photo, or socialLink.

  • value (required): The value to search for.

  • userEmail (optional): Restrict results to a specific user.

⚠️ Important: You must pass key and value as two separate query parameters. Passing only the field name (e.g. ?email=...) will cause an error.

Example requests:

GET https://sourcewhale.app/public-api/v1/candidates/search?key=email&value=jane.smith@example.com

GET https://sourcewhale.app/public-api/v1/candidates/search?key=phone&value=+447911123456

GET https://sourcewhale.app/public-api/v1/candidates/search?key=socialLink&value=https://linkedin.com/in/janesmith

Response: Returns a list of matching contact objects.

Update a Contact: POST /v1/candidates/modify

Update the fields of an existing contact.

  • candidate (required): Object containing candidateId plus the fields to update.

Response: Returns "success" on completion.

Example request:

POST https://sourcewhale.app/public-api/v1/candidates/modify{
  "candidate": {
    "candidateId": "your_candidate_id_here",
    "email": "updated.email@example.com",
    "phone": "+447911000000"
  }
}

Campaigns

List Campaigns: GET /v1/campaigns/list

Retrieve all live campaigns for your team.

  • userEmail (optional): Filter to campaigns created by a specific user.

  • includeMetrics (optional, true/false): Include open rate, reply rate, interest rate, and booked rate.

Response: Returns a list of campaigns with campaignId and campaignName.

Example requests:

GET https://sourcewhale.app/public-api/v1/campaigns/list

GET https://sourcewhale.app/public-api/v1/campaigns/list?userEmail=recruiter@yourcompany.com&includeMetrics=true

Projects

List Projects: GET /v1/projects/list

Retrieve all projects for your team.

  • userEmail (optional): Filter to projects created by a specific user.

Response: Returns a list of projects with projectId and projectName.

Example requests:

GET https://sourcewhale.app/public-api/v1/projects/list

GET https://sourcewhale.app/public-api/v1/projects/list?userEmail=recruiter@yourcompany.com

Statistics

Dashboard Statistics: GET /v1/statistics/dashboard

Retrieve outreach statistics for your team over a date range.

  • from (required): Start date in YYYY-MM-DD format.

  • to (required): End date in YYYY-MM-DD format.

  • timezone (optional): Timezone string (e.g. Europe/London). Defaults to UTC.

Response: Returns counts for sourced, sent, opened, replied, interested, and booked across the date range.

Example requests:

GET https://sourcewhale.app/public-api/v1/statistics/dashboard?from=2026-01-01&to=2026-03-31

GET https://sourcewhale.app/public-api/v1/statistics/dashboard?from=2026-01-01&to=2026-03-31&timezone=America/New_York

GET https://sourcewhale.app/public-api/v1/statistics/dashboard?from=2026-01-01&to=2026-03-31&timezone=Europe/London

Webhooks

Subscribe to Events: POST /v1/zapier/subscribe

Register a webhook URL to receive real-time notifications when contacts are added or updated in SourceWhale.

Request body:

  • url (required): The webhook URL to receive event payloads.

  • subscriptionType (required): The event type to subscribe to. Accepted values:

    • candidateCreated: fires when a new contact is added to SourceWhale for the first time.

    • candidateUpdated: fires when an existing contact's data is modified.

  • triggerKeys (optional, array, candidateUpdated only): Limit which fields trigger the webhook. For example, ["email", "phone"] will only fire when those specific fields change. If omitted, any field change triggers the webhook.

Response: Returns an id (subscriptionId) for this webhook registration.

Example: trigger when a new contact is added:

POST /v1/zapier/subscribe {"url": "https://your-webhook-url.com/endpoint",  "subscriptionType": "candidateCreated"}

Example: trigger only when a contact's email or phone changes:

POST /v1/zapier/subscribe { "url": "https://your-webhook-url.com/endpoint",  "subscriptionType": "candidateUpdated",  "triggerKeys": ["email", "phone"]}

The webhook payload will contain { "candidate": { ...contactObject } }.

Common Issues and FAQs

"Header name must be a valid HTTP Token" error

This error means your API key header name contains an invalid character, most commonly a space. HTTP header names cannot contain spaces.

Fix: Make sure the header is named exactly API-Key (with a hyphen, not a space). In Postman, go to the Headers tab and check the header name.

  • Incorrect: API Key (space)

  • Correct: API-Key (hyphen)

Getting a 502 error on the Search Contacts endpoint

A 502 on GET /v1/candidates/search is usually caused by missing query parameters. The endpoint requires both key and value as separate parameters.

Fix: Make sure you are passing two separate parameters, not just the field name on its own.

In Postman, set these up in the Params tab as two separate rows:

My API key is not working

Check the following:

  • The header name is API-Key (hyphen, not space, not Authorization).

  • You are using the key generated for your team. Only admin users can generate API keys (via Admin > Settings > Generate API Key).

  • The key has not been regenerated. Generating a new key invalidates the previous one.

What date format should I use for statistics queries?

Dates must be in YYYY-MM-DD format (e.g. 2026-01-31). Other formats such as 01/31/2026 or 31-01-2026 will not work.

What does the optional userEmail parameter do?

Several endpoints accept a userEmail query parameter. When provided, results are scoped to that user only (e.g. only their campaigns, projects, or contacts). If omitted, the request returns data for the whole team.

What values can I use for the key parameter on Search Contacts?

The key parameter accepts one of four values:

  • email: search by email address

  • phone: search by phone number

  • photo: search by profile photo URL

  • socialLink: search by social profile URL (e.g. LinkedIn)


Stuck or need some help? Click on the chat icon at the bottom right-hand corner to connect with our support team!

Did this answer your question?