mySDRDocs

API reference

Enrich Companies

Send exactly one of linkedin_urls, domains or names, with up to 25 entries. Each entry gets its own result, in the order you sent them, with a list of matches.

POSThttps://mysdr.app/api/v1/company/enrich
View Markdown

Each entry gives at most one company. A LinkedIn URL gives that page. A domain gives the company on exactly that domain; set exact_match to false to also accept a company the source ties to the domain on another one (confidence_score is then null). A name gives the company with exactly that name, or else the best match (confidence_score 1.0 on an exact name, null otherwise); set exact_match to true to keep only exact names. To choose between companies that share a name, use the free GET /companies/lookup and enrich the page you pick.

fields picks the groups: basic_info (the default), headcount, locations, taxonomy, followers, funding and hiring. A value we cannot fill is null, and its path is listed in unavailable, so you can tell "unknown" from "zero".

Every company found costs one credit, whatever groups you ask for; the open roles in hiring are included. Not found, invalid, capped or failed entries cost nothing, and the same company asked twice is looked up and charged once, also in two forms (a numeric LinkedIn page and its slug, or a domain and the page of the same company).

Send Authorization: Bearer gtk_…. Create the key under Connect assistant → API keys. A missing, invalid or revoked key is 401. A valid key while this API is not enabled for your organization answers 403 api_not_enabled, with what the key can do instead. Every response includes mySDR-Api-Version, mySDR-Request-Id and Cache-Control: no-store, and a response to an accepted key also X-RateLimit-* (so not a 401, a 405, an OPTIONS or a 404 for an unknown path).

Jobs

Add hiring to fields to get the open roles. company.hiring gives openings_count, the number of open roles on LinkedIn, and recent_openings: the newest roles, newest first, each with title, url, location and posted_on. The roles cost nothing extra: a company found is 1 credit, whatever groups you ask for. A value we cannot fill is null and listed in unavailable.

{
  "linkedin_urls": [
    "https://www.linkedin.com/company/acme-analytics"
  ],
  "fields": [
    "basic_info",
    "hiring"
  ]
}

Authentication

Send your API key as a Bearer token: Authorization: Bearer gtk_…. Create the key under Connect assistant → API keys. A missing, invalid or revoked key is 401, including while an API is closed. On an endpoint of the Signals API or the Company API, a valid key while that API is closed for your organization answers 403 api_not_enabled, with what the key can do instead; the other endpoints work with every key. Every response includes mySDR-Api-Version, mySDR-Request-Id and Cache-Control: no-store, and a response to an accepted key also X-RateLimit-* (so not a 401, a 405, an OPTIONS or a 404 for an unknown path); every error has type, message, param and request_id.

Body parameters

  • linkedin_urls string[] — LinkedIn company pages, e.g. https://www.linkedin.com/company/acme-analytics.
  • domains string[] — Company websites or domains, e.g. acme-analytics.example.
  • names string[] — Company names.
  • fields string[] — Groups to return. Defaults to ["basic_info"]. One of: basic_info, headcount, locations, taxonomy, followers, funding, hiring.
  • exact_match boolean — Domains: only a company on exactly that domain (defaults to true). Names: only a company with exactly that name (defaults to false: the best match).
  • max_credits integer — Stop before the call costs more than this. An entry is looked up only while its company still fits; an entry that finds nothing costs nothing and leaves the room to the next. Entries left over are capped. Below the cost of one company the call is 402 max_credits_exceeded.

Response

  • results object[] — One entry per input, in the same order.
  • results[].input string — The input as you sent it.
  • results[].status string — matched, not_found, invalid (not a LinkedIn company URL, domain or name), capped (not looked up: max_credits had no room left) or error (lookup failed; retry later). One of: matched, not_found, invalid, capped, error.
  • results[].match_type string — linkedin_url, domain or name. One of: linkedin_url, domain, name.
  • results[].matches object[] — confidence_score and company: one company when the status is matched, otherwise empty.
  • results[].matches[].confidence_score number | null — 1 on a LinkedIn URL, on exactly the domain you sent or on exactly the name you sent; null otherwise (a company on another domain with exact_match false, or the best match on a name).
  • results[].matches[].company object — The company. See the fields below.
  • results[].message string — On not_found, invalid and capped: why, and what to send instead.
  • company.linkedin_url string | null — The company page.
  • company.basic_info object — name, linkedin_url, website, primary_domain, description, tagline, logo_url, employee_count_range, company_type, year_founded.
  • company.headcount object — total (employees on LinkedIn) and range. Growth, role mix and region mix are null and listed in unavailable.
  • company.locations object — headquarters, city, state, country, country_code, street_address, postal_code and all_office_addresses.
  • company.taxonomy object — industry and specialities.
  • company.followers object — count. Follower growth is null and listed in unavailable.
  • company.funding object — last_round_type, last_round_amount_usd, last_fundraise_date, investors and rounds (newest first), from the funding rounds we track.
  • company.hiring object — openings_count (open roles on LinkedIn) and recent_openings: the newest roles, with title, url, location and posted_on.
  • company.unavailable string[] — Paths in the requested groups that this API cannot fill for this company.
  • credits_used integer — Credits this call used.
  • truncated_by string — Only when max_credits left entries capped: max_credits. One of: max_credits.

Credits

1 credit per company found. Errors and empty lookups are free. A call that spent credits puts that number in credits_used, in X-Credits-Used and in X-Credits-Charged. When the wallet can be read, the response also sends X-Credits-Remaining.

Errors

  • 400 invalid_request — The body is not valid JSON, a field is unknown or has the wrong type, or a value is not allowed.
  • 401 authentication_error — The Authorization header is missing, or the key is unknown or revoked.
  • 403 permission_error — API access is not part of your plan, or your account is suspended.
  • 403 api_not_enabled — The key is valid, but the Signals API or the Company API is not enabled for your organization yet. The error says what this key can do.
  • 429 rate_limit_error — More than 60 requests per minute, or more than 3 at the same time, on one key. Wait for the Retry-After header.
  • 429 daily_limit_reached — The request could take your organization over its daily credit limit. The limit resets at midnight (Europe/Brussels).
  • 502 upstream_error — The data source did not answer. Retry later.
  • 503 service_unavailable — The API is temporarily unavailable. Retry later.
  • 500 internal_error — Something went wrong on our side.

Example

cURL

curl -X POST "https://mysdr.app/api/v1/company/enrich" \
  -H "Authorization: Bearer $MYSDR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "linkedin_urls": [
      "https://www.linkedin.com/company/acme-analytics"
    ],
    "fields": [
      "basic_info",
      "headcount"
    ]
  }'

JavaScript

const response = await fetch('https://mysdr.app/api/v1/company/enrich', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.MYSDR_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "linkedin_urls": [
      "https://www.linkedin.com/company/acme-analytics"
    ],
    "fields": [
      "basic_info",
      "headcount"
    ]
  })
});
const body = await response.json();

Python

import json
import os
import urllib.request

payload = {
  "linkedin_urls": [
    "https://www.linkedin.com/company/acme-analytics"
  ],
  "fields": [
    "basic_info",
    "headcount"
  ]
}

request = urllib.request.Request(
    "https://mysdr.app/api/v1/company/enrich",
    headers={
    "Authorization": f"Bearer {os.environ['MYSDR_API_KEY']}",
    "Content-Type": "application/json"
    },
    data=json.dumps(payload).encode(),
    method="POST",
)
with urllib.request.urlopen(request) as response:
    body = json.load(response)

Example response

{
  "results": [
    {
      "input": "https://www.linkedin.com/company/acme-analytics",
      "status": "matched",
      "match_type": "linkedin_url",
      "matches": [
        {
          "confidence_score": 1,
          "company": {
            "linkedin_url": "https://www.linkedin.com/company/acme-analytics",
            "basic_info": {
              "name": "Acme Analytics",
              "linkedin_url": "https://www.linkedin.com/company/acme-analytics",
              "website": "https://acme-analytics.example",
              "primary_domain": "acme-analytics.example",
              "description": "Analytics for finance teams.",
              "tagline": null,
              "logo_url": null,
              "employee_count_range": "51-200",
              "company_type": "Privately Held",
              "year_founded": 2019
            },
            "headcount": {
              "total": 87,
              "range": "51-200",
              "growth_percent": {
                "1m": null,
                "3m": null,
                "6m": null,
                "12m": null
              },
              "growth_absolute": {
                "1m": null,
                "3m": null,
                "6m": null,
                "12m": null
              },
              "by_role": null,
              "by_region": null,
              "largest_headcount_country": null
            },
            "unavailable": [
              "headcount.growth_percent",
              "headcount.growth_absolute",
              "headcount.by_role",
              "headcount.by_region",
              "headcount.largest_headcount_country"
            ]
          }
        }
      ]
    }
  ],
  "credits_used": 1
}