mySDRDocs

API reference

Update a company

Changes where a company stands in your work: its status with a reason, a snooze until the rescan, what it said, your next action, its general addresses and contact form, your own fields. Send only what changes. {id} is its id, one of its saved_ids, or its domain or LinkedIn page; a company that is not in the table yet is added by its domain or page (pass name). A status change is logged. mySDR keeps your whole process, so the user never needs a spreadsheet next to it: the state of each company and person (status with a reason, next action, email and contact points, your own fields), every email, reply and bounce you log, the exclusions, and a check before every send. The user sees all of it in the Leads and Companies tabs.

PATCHhttps://mysdr.app/api/v1/tables/companies/{id}
View Markdown

Authentication

Send Authorization: Bearer gtk_…. Create the key under Connect assistant → API keys. Every gtk_ key can call these routes, also while the Signals API is closed. A missing, invalid or revoked key is 401.

Path parameters

  • id string · required — The row, a domain or a LinkedIn page (URL-encoded).

Body parameters

  • status string — new (in the work), needs_decision (waits for the user; say why in status_reason), snoozed (until snooze_until, then new again) or archived (out; say why). One of: new, needs_decision, snoozed, archived.
  • status_reason string | null — Why, in a few words: "Below 50 FTE", "Rescan 23/11". Up to 500 characters.
  • snooze_until string | null — The day the row comes back as new: a date (2026-11-23, 09:00 Brussels time) or an ISO time. Alone it snoozes the row.
  • lead_status string | null — What they said. not_interested also stops LinkedIn for them and blocks a new sequence. One of: interested, meeting, later, not_interested.
  • next_action object | null — Your next step and when: at (a date or ISO time), kind (follow_up, recontact, rescan, approval, other), note, and email when that step is an email you will send yourself: { "text", "subject", "step", "template", "to" } (text required, up to 20,000 characters; subject up to 200 and template up to 80, as in POST /outreach/activity; step 1 to 20; to only if it is not the row’s address; kind defaults to follow_up). The user sees the planned email on Templates, with the emails you already logged above it, and GET /agenda gives it back on its day, so you keep no copy. A list (GET /tables/leads, /tables/companies) gives it without text; one row (GET /tables/leads/{id}, /tables/companies/{id}), the response of a change and GET /agenda give the text. Logging email_sent with the same step clears it (logged without a step, it clears one planned without a step), and so do a reply, a meeting, a bounce, an unsubscribe, a referral and not_interested; plan the next one. A new next_action replaces the current one and the email planned for it (replaced in the response gives them back); null clears both. GET /agenda lists the due ones.
  • out_of_office_until string | null — Away until this day (from an out-of-office reply).
  • contact_points object[] — Replaces the list of general addresses and contact forms: { "email": "jobs@acme.com", "label": "jobs", "source_url": "…", "email_status": "verified" } or { "form": "https://acme.com/contact" }. Up to 20.
  • add_contact_points object[] — Adds or updates these (the same address or form is updated), keeping the others.
  • fields object — Your own columns, merged with what is there: a name in lowercase letters, digits and _ (fte, ats, open_roles) with a value (text, number, true/false) or { "value", "label", "source_url", "observed_at" }; null removes one. Up to 40 per row. The user sees them as columns.
  • campaign_id string — Put the row in this campaign (POST /outreach/campaigns, or one from a LinkedIn sequence).
  • campaign_ids string[] — Replaces the campaigns of the row.
  • stage string | null — One of the organization's own stages (GET /stages), by its key (mql) or its name ("MQL"); null clears it. A stage sits next to status: it stops nothing and changes no status. A change is logged.
  • owner string | null — Who in the team follows the row up: me (the user behind the key), or the email address or user id of a colleague (GET /team); null clears it. A change is logged.
  • note string | null — Your note on the row, up to 500 characters.
  • name string — The name, when the company is added by its domain or page.

Response

  • id string · required — The row: what list, PATCH and DELETE take.
  • object string · required — person or company.
  • name string · required — Its name.
  • domain string | null — Its domain.
  • linkedin_url string | null — Its LinkedIn page.
  • status string · required — Its status now.
  • status_reason string | null — Why.
  • snooze_until string | null — While snoozed: until when.
  • lead_status string | null — What they said.
  • next_action object | null — at, kind, note.
  • out_of_office_until string | null — While out of office: until when.
  • contact_points object[] — Its general addresses and forms.
  • fields object — Your own fields.
  • campaign_ids string[] — Its campaigns.
  • stage string | null — Its stage.
  • owner_id string | null — The user id of its owner.
  • owner object | null — With owner or stage in the body: the owner (id, name, email).
  • note string | null — Your note on the row.
  • changed boolean · required — Something changed.
  • replaced object — When this call set another next action (or null): the one it replaced, { next_action: { at, kind, note, email } }, with the full text of its planned email, so you can put it back.
  • added_to_table boolean · required — The row was not in the table before this call (a company by its domain or page).
  • stopped_linkedin_sequences integer — With lead_status not_interested: the LinkedIn sequences that stopped.
  • dashboard_url string · required — The table in mySDR.

Credits

Free. This call never uses credits.

Errors

  • 400 invalid_request — An unknown field (email belongs to a person; a company has contact_points), nothing to change, or a value that is not valid.
  • 404 not_found — No company matches, and the id is not a domain or page to add it by.
  • 409 invalid_state — The key has no user behind it, so mySDR cannot record who did it.
  • 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.
  • 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.
  • 503 service_unavailable — The API is temporarily unavailable. Retry later.
  • 500 internal_error — Something went wrong on our side.

Example

cURL

curl -X PATCH "https://mysdr.app/api/v1/tables/companies/acme-logistics.example" \
  -H "Authorization: Bearer $MYSDR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "snoozed",
    "snooze_until": "2026-11-23",
    "status_reason": "Rescan: only 2 open roles",
    "add_contact_points": [
      {
        "email": "jobs@acme-logistics.example",
        "label": "jobs",
        "source_url": "https://acme-logistics.example/contact",
        "email_status": "catch_all"
      }
    ],
    "fields": {
      "fte": {
        "value": 233,
        "label": "FTE",
        "source_url": "https://example.org/annual-accounts"
      },
      "ats": "Recruitee"
    }
  }'

JavaScript

const response = await fetch('https://mysdr.app/api/v1/tables/companies/acme-logistics.example', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.MYSDR_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "status": "snoozed",
    "snooze_until": "2026-11-23",
    "status_reason": "Rescan: only 2 open roles",
    "add_contact_points": [
      {
        "email": "jobs@acme-logistics.example",
        "label": "jobs",
        "source_url": "https://acme-logistics.example/contact",
        "email_status": "catch_all"
      }
    ],
    "fields": {
      "fte": {
        "value": 233,
        "label": "FTE",
        "source_url": "https://example.org/annual-accounts"
      },
      "ats": "Recruitee"
    }
  })
});
const body = await response.json();

Python

import json
import os
import urllib.request

payload = {
  "status": "snoozed",
  "snooze_until": "2026-11-23",
  "status_reason": "Rescan: only 2 open roles",
  "add_contact_points": [
    {
      "email": "jobs@acme-logistics.example",
      "label": "jobs",
      "source_url": "https://acme-logistics.example/contact",
      "email_status": "catch_all"
    }
  ],
  "fields": {
    "fte": {
      "value": 233,
      "label": "FTE",
      "source_url": "https://example.org/annual-accounts"
    },
    "ats": "Recruitee"
  }
}

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

Example response

{
  "id": "sav_2b9e8d10-7f4a-4a51-8c2e-5d1f0a3b6c77",
  "object": "company",
  "name": "Acme Logistics",
  "domain": "acme-logistics.example",
  "linkedin_url": null,
  "status": "snoozed",
  "status_reason": "Rescan: only 2 open roles",
  "snooze_until": "2026-11-23T08:00:00.000Z",
  "lead_status": null,
  "next_action": null,
  "out_of_office_until": null,
  "contact_points": [
    {
      "kind": "email",
      "value": "jobs@acme-logistics.example",
      "label": "jobs",
      "source_url": "https://acme-logistics.example/contact",
      "email_status": "catch_all"
    }
  ],
  "fields": {
    "fte": {
      "value": 233,
      "label": "FTE",
      "source_url": "https://example.org/annual-accounts",
      "observed_at": "2026-10-23T09:00:00.000Z"
    },
    "ats": {
      "value": "Recruitee",
      "label": null,
      "source_url": null,
      "observed_at": "2026-10-23T09:00:00.000Z"
    }
  },
  "campaign_ids": [],
  "note": null,
  "changed": true,
  "added_to_table": true,
  "dashboard_url": "https://mysdr.app/en/gtm/companies"
}