SoundGTM API reference

Overview for technology partners

This is for a company building a tool that talks to SoundGTM on behalf of a shared customer. SoundGTM offers a plain REST API under /api/v1 for enrolling referral partners and handing back their tracking links, reading a customer's deals, partners, programs and commissions, and acting on them (stage moves, conversions, invites, commission approvals, announcements). The same tools are also served over MCP for AI assistants. Every call works inside one customer's SoundGTM workspace and carries that customer's permissions.

What you can do, and what you need for each

You want toUseThe customer gives you
Enroll a person as the customer's referral partner from your product and get their tracking link, no invite emailREST: POST /api/v1/partners/register (see Partner registration API)A Read + Write API key or OAuth connection, from a user who can invite referral partners
Look up an existing referral partner's tracking linkREST: GET /api/v1/partners/registerA Read or Read + Write API key or OAuth connection, from a user who can view partners
Read a customer's pipeline, deals, partners, programs, pending commissions and action queueREST (GET) or the MCP serverA Read API key or an OAuth connection, on the Growth plan or above
Act in the customer's workspace: move a deal stage, mark a deal converted, invite a partner, authorize commissions, send an announcement, and the other write tools in the list belowREST (POST/PUT) or the MCP serverA Read + Write API key, or an OAuth connection approved with Read + Write, on the Growth plan or above

Where the customer gets the key or connection

  • API key: Settings → AI / MCP → + Create API key. Choose Read or Read + Write (the key form labels them "Read only" and "Read & write"; the OAuth approval screen says "Read only" and "Read + Write"); the key is shown once. You send it as Authorization: Bearer pt_sk_….
  • OAuth connection (Claude, ChatGPT, Gemini): the customer adds SoundGTM from inside the assistant, and the approval screen names the access level. The admin approving the connection chooses Read or Read + Write on that screen; if the client sends no scope, the screen starts on Read + Write when the client's redirect address is on claude.ai, chatgpt.com or openai.com and on Read for every other client, Gemini included, so request read_write if you need writes. How Claude and ChatGPT connect is described on the MCP integration page; a tool of your own can use an API key, or register itself as an OAuth client (POST /api/oauth/register, standard dynamic client registration) and send the customer through the approval screen; every client is public (no client secret) and must use PKCE (S256) with https redirect addresses (or http://localhost). Connections are listed and revocable under Settings → AI / MCP → Connected AI assistants (OAuth).
  • The customer must be a company account (a referral-partner account gets 403), and creating the key or approving the connection needs the organization-settings permission (the AI / MCP tab in Settings is shown to admins). A key acts with its creator's permissions. Every REST call except /partners/register, and the MCP server, need the Growth plan or above, and on plans that cap monthly AI usage, an unspent monthly AI-draft allowance (otherwise 403, on every endpoint covered by the plan check). On /partners/register the only plan check is the partner limit, applied when a call creates or reactivates a partner. Revoking a key or connection takes effect on the next request (401); an expired OAuth access token is also a 401, so refresh it before assuming access was revoked.

REST conventions

Reads are GET with inputs in the query string; writes are POST or PUT with a JSON body. A write needs a Read + Write key, or an OAuth connection approved with Read + Write, and the customer's own permission for that action. Errors come back as a JSON body with an error message and an HTTP status; the Partner registration API below lists its own statuses.

The method, path, inputs and permission for every tool route are listed under MCP tools below.

Not available yet

  • No outbound webhooks from SoundGTM to your tool.
  • No sandbox. Registering a partner creates a real pending partner that counts against the customer's partner limit, and it cannot be undone over the API; sending the same email and program again returns the same link, except that for a partner the customer deactivated it re-enrolls them (and uses a partner-limit slot).
  • Other calls run against the customer's real workspace, and writes are live: stage moves and commission approvals take effect, and announcements and partner invites send real email. Test reads with a key set to Read (choose it in the key form; Read + Write is preselected), and only point a Read + Write key at a workspace you are prepared to change.

Interfaces

The rest of this page has two parts: the MCP tools, which an AI assistant calls on your behalf and which are also served over REST, and the Partner registration API, which your own software calls to register referral partners.

The MCP tools are reached through OAuth (claude.ai, ChatGPT, Gemini, or a tool registered as an OAuth client) or an API key; the Partner registration API takes an API key or an OAuth connection. Create keys in Settings → AI / MCP. Setup guides for Claude and ChatGPT are on the MCP integration page.

MCP tools

Every tool the SoundGTM MCP server serves, with the inputs it accepts and the permission the signed-in user (or key owner) needs. Read tools work with a Read key or OAuth connection; tools marked Read + Write need a Read + Write key, or an OAuth connection approved with Read + Write. This section is generated from the server's own tool definitions, so the tools, their inputs and their required permissions stay in step with the server. Each tool that shows a REST line under its name is also served over REST at that method and path, with the same API key or OAuth connection (sent as a Bearer token), plan and permission checks: reads take their inputs in the query string, writes in a JSON body, and any {name} in the path is filled in from the input of that name. Value limits (such as a maximum) are enforced by the server and are not all listed here.

pipeline_summary

Deal counts by stage, at-risk count, pending commission totals

Access: Read · Permission: View pipeline

REST: GET /api/v1/pipeline · inputs go in the query string

curl "https://partnertracker.soundgtm.com/api/v1/pipeline" -H "Authorization: Bearer $SOUNDGTM_API_KEY"

This tool takes no inputs.

list_deals

List deals with filters (stage, partner, risk, source)

Access: Read · Permission: View pipeline

REST: GET /api/v1/deals · inputs go in the query string

curl "https://partnertracker.soundgtm.com/api/v1/deals" -H "Authorization: Bearer $SOUNDGTM_API_KEY"
InputTypeRequiredDescription
stagestringNoFilter by stage name (exact match)
partner_idstringNoFilter by partner UUID
risk_color"green" | "amber" | "red"NoFilter by risk color
sourcestringNoFilter by source (e.g. referral_registration)
limitintegerNoMax results (default 50)

list_stalled_deals

Deals with amber or red risk scores

Access: Read · Permission: View pipeline

REST: GET /api/v1/deals/stalled · inputs go in the query string

curl "https://partnertracker.soundgtm.com/api/v1/deals/stalled" -H "Authorization: Bearer $SOUNDGTM_API_KEY"
InputTypeRequiredDescription
limitintegerNoMax results (default 25)

get_deal

Full deal detail: members, recent events

Access: Read · Permission: View pipeline

REST: GET /api/v1/deals/{deal_id} · a {name} in the path is required over REST (the Required column below describes the MCP tool) and is filled in from the input of that name; the other inputs go in the query string

curl "https://partnertracker.soundgtm.com/api/v1/deals/<deal_id>" -H "Authorization: Bearer $SOUNDGTM_API_KEY"
InputTypeRequiredDescription
deal_idstringYesDeal UUID

list_partners

List partners with filters (status, at-risk)

Access: Read · Permission: View partners

REST: GET /api/v1/partners · inputs go in the query string

curl "https://partnertracker.soundgtm.com/api/v1/partners" -H "Authorization: Bearer $SOUNDGTM_API_KEY"
InputTypeRequiredDescription
status"active" | "inactive"NoDefault: "active".
at_riskbooleanNoIf true, returns only at-risk partners (health color red or amber)
limitintegerNoDefault: 50.

get_partner_detail

Partner's deals, commission terms, health score

Access: Read · Permission: View partners

REST: GET /api/v1/partners/{partner_id} · a {name} in the path is required over REST (the Required column below describes the MCP tool) and is filled in from the input of that name; the other inputs go in the query string

curl "https://partnertracker.soundgtm.com/api/v1/partners/<partner_id>" -H "Authorization: Bearer $SOUNDGTM_API_KEY"
InputTypeRequiredDescription
partner_idstringYesPartner UUID

list_programs

Your partner programs and their settings

Access: Read · Permission: View partners

REST: GET /api/v1/programs · inputs go in the query string

curl "https://partnertracker.soundgtm.com/api/v1/programs" -H "Authorization: Bearer $SOUNDGTM_API_KEY"

This tool takes no inputs.

get_action_queue

Your prioritized do-this-next queue

Access: Read · Permission: View pipeline

REST: GET /api/v1/action-queue · inputs go in the query string

curl "https://partnertracker.soundgtm.com/api/v1/action-queue" -H "Authorization: Bearer $SOUNDGTM_API_KEY"
InputTypeRequiredDescription
limitintegerNoDefault: 20.

get_ideal_partner_profile

Your saved Ideal Partner Profile

Access: Read · Permission: View partners

REST: GET /api/v1/ideal-partner-profile · inputs go in the query string

curl "https://partnertracker.soundgtm.com/api/v1/ideal-partner-profile" -H "Authorization: Bearer $SOUNDGTM_API_KEY"

This tool takes no inputs.

list_pending_commissions

All commissions awaiting payment

Access: Read · Permission: View payments

REST: GET /api/v1/commissions/pending · inputs go in the query string

curl "https://partnertracker.soundgtm.com/api/v1/commissions/pending" -H "Authorization: Bearer $SOUNDGTM_API_KEY"
InputTypeRequiredDescription
limitintegerNoDefault: 50.

update_deal_stage

Move a deal to a new stage

Access: Read + Write · Permission: Edit deals

REST: POST /api/v1/deals/{deal_id}/stage · a {name} in the path is required over REST (the Required column below describes the MCP tool) and is filled in from the input of that name; the other inputs go in the JSON body

curl -X POST "https://partnertracker.soundgtm.com/api/v1/deals/<deal_id>/stage" -H "Authorization: Bearer $SOUNDGTM_API_KEY" -H "Content-Type: application/json" -d '{"stage":"<stage>"}'
InputTypeRequiredDescription
deal_idstringYesDeal UUID
stagestringYesNew stage name

convert_deal

Mark a deal as converted — creates payout records and notifies the partner if the program notifies partners

Access: Read + Write · Permission: Convert deals

REST: POST /api/v1/deals/{deal_id}/convert · a {name} in the path is required over REST (the Required column below describes the MCP tool) and is filled in from the input of that name; the other inputs go in the JSON body

curl -X POST "https://partnertracker.soundgtm.com/api/v1/deals/<deal_id>/convert" -H "Authorization: Bearer $SOUNDGTM_API_KEY" -H "Content-Type: application/json" -d '{}'
InputTypeRequiredDescription
deal_idstringYesDeal UUID
notesstringNoOptional conversion notes

attach_deal_to_partner

Attach an unattributed deal to an existing partner, or to a new partner created on the spot (no email, no portal access)

Access: Read + Write · Permission: Edit deals

REST: POST /api/v1/deals/{deal_id}/partner · a {name} in the path is required over REST (the Required column below describes the MCP tool) and is filled in from the input of that name; the other inputs go in the JSON body

curl -X POST "https://partnertracker.soundgtm.com/api/v1/deals/<deal_id>/partner" -H "Authorization: Bearer $SOUNDGTM_API_KEY" -H "Content-Type: application/json" -d '{"partner_id":"<partner_id>"}'
InputTypeRequiredDescription
deal_idstringYesDeal UUID
partner_idstringNoExisting partner UUID to attach to
new_partner_namestringNoCreate a new partner with this company name and attach the deal to it
new_partner_emailstringNoOptional contact email for the new partner — stored, not emailed

invite_partner

Send a partner invite email

Access: Read + Write · Permission: Invite referral partners

REST: POST /api/v1/partners/invite · inputs go in the JSON body

curl -X POST "https://partnertracker.soundgtm.com/api/v1/partners/invite" -H "Authorization: Bearer $SOUNDGTM_API_KEY" -H "Content-Type: application/json" -d '{"email":"<email>","program_id":"<program_id>"}'
InputTypeRequiredDescription
emailstring (email)YesPartner's email address
program_idstringYesUUID of the program to invite this partner to
company_namestringNoPartner's company name
payout_rule_idstringNoUUID of the payout rule to attach to this partner

save_ideal_partner_profile

Create or replace your Ideal Partner Profile

Access: Read + Write · Permission: Add & edit partners

REST: PUT /api/v1/ideal-partner-profile · inputs go in the JSON body

curl -X PUT "https://partnertracker.soundgtm.com/api/v1/ideal-partner-profile" -H "Authorization: Bearer $SOUNDGTM_API_KEY" -H "Content-Type: application/json" -d '{"profile_markdown":"<profile_markdown>","prospect_description":"<prospect_description>"}'
InputTypeRequiredDescription
profile_markdownstringYesThe full profile as markdown
prospect_descriptionstringYesOne-paragraph prospect-finder description

authorize_commissions

Bulk-approve commissions for payment (does not send money — transfers stay on the Payments page)

Access: Read + Write · Permission: Authorize payments

REST: POST /api/v1/commissions/authorize · inputs go in the JSON body

curl -X POST "https://partnertracker.soundgtm.com/api/v1/commissions/authorize" -H "Authorization: Bearer $SOUNDGTM_API_KEY" -H "Content-Type: application/json" -d '{"payment_ids":["<payment_id>"]}'
InputTypeRequiredDescription
payment_idsarray of string (uuid)YesList of payment UUIDs to authorize

mark_commission_paid

Record a commission you already paid outside SoundGTM (bookkeeping only — sends no money)

Access: Read + Write · Permission: Manage payment status

REST: POST /api/v1/commissions/{payment_id}/paid · a {name} in the path is required over REST (the Required column below describes the MCP tool) and is filled in from the input of that name; the other inputs go in the JSON body

curl -X POST "https://partnertracker.soundgtm.com/api/v1/commissions/<payment_id>/paid" -H "Authorization: Bearer $SOUNDGTM_API_KEY" -H "Content-Type: application/json" -d '{}'
InputTypeRequiredDescription
payment_idstringYesPayment UUID
payment_referencestringNoReference number or note (e.g. wire transfer ID)

send_announcement

Send an announcement to all or selected partners

Access: Read + Write · Permission: Send announcements

REST: POST /api/v1/announcements · inputs go in the JSON body

curl -X POST "https://partnertracker.soundgtm.com/api/v1/announcements" -H "Authorization: Bearer $SOUNDGTM_API_KEY" -H "Content-Type: application/json" -d '{"title":"<title>","body":"<body>","audience":"select_partners","partner_ids":["i:<partner_id>"]}'
InputTypeRequiredDescription
titlestringYesAnnouncement title
bodystringYesAnnouncement body text
audience"all_partners" | "imported_only" | "referral_partners_only" | "select_partners"NoWho receives this announcement. Default: "all_partners".
partner_idsarray of stringNoRequired when audience is 'select_partners'. Use prefixed IDs: 'i:uuid' for imported partners, 'r:uuid' for referral partner orgs.

draft_partner_email

Create a Gmail draft addressed to a partner — never sends

Access: Read + Write · Permission: Add & edit partners

REST: POST /api/v1/partners/{partnerId}/email-draft · a {name} in the path is required over REST (the Required column below describes the MCP tool) and is filled in from the input of that name; the other inputs go in the JSON body

curl -X POST "https://partnertracker.soundgtm.com/api/v1/partners/<partnerId>/email-draft" -H "Authorization: Bearer $SOUNDGTM_API_KEY" -H "Content-Type: application/json" -d '{"to":"<to>","body":"<body>"}'
InputTypeRequiredDescription
tostring (email)YesRecipient email address
subjectstringNoEmail subject. Default: "Check-in".
bodystringYesEmail body (plain text)
partnerIdstringNoIf this draft is a check-in to a specific partner (e.g. a quiet-partner wake-up), that partner's id — records that a check-in was drafted for them.

Partner registration API

Third-party tools (such as Social OS) can register referral partners programmatically and receive their tracking link without going through the invite email flow. This is useful when your tool already handles outreach and you want SoundGTM to issue the referral link silently.

Authentication: a Read + Write API key or OAuth connection (see where the customer gets the key or connection above), sent as a Bearer token, from a user who can invite referral partners.

Endpoint: POST /api/v1/partners/register

Request body:

{
  "email": "jane@example.com",
  "name": "Jane Smith",
  "linkedin_url": "https://linkedin.com/in/janesmith",
  "program_id": "uuid-of-your-program"
}
  • email is required. name, linkedin_url, and program_id are optional.
  • If program_id is omitted, the partner is enrolled in your default program.

Response:

  • 201: a new partner, or a deactivated one re-enrolled.
  • 200: a link already exists for that email and program, pending or active.

Both statuses return the same body:

{
  "referral_link_id": "uuid",
  "referral_url": "https://partnertracker.soundgtm.com/r/AbCd1234"
}

Pass referral_url to your tool to embed in outreach messages. Clicks on that link are attributed to the partner in SoundGTM.

The call is idempotent — calling it again with the same email and program returns the same link without creating a duplicate (200). The exception is a partner the customer deactivated: registering them again re-enrolls them as Pending (201) and uses a partner-limit slot. On either repeat call name and linkedin_url are not updated.

No invite email is sent. The partner appears as Pending in your partner list until they claim their SoundGTM account via the invite flow.

Failed calls are covered under Error statuses below.

To fetch an existing partner's referral link without creating or changing anything, call the same endpoint with GET:

Endpoint: GET /api/v1/partners/register?email=jane%40example.com

  • email is required; URL-encode it, because an unencoded character such as + changes the address the route receives. Add &program_id=<uuid> to target a specific program; omit it to use your default program. If you have no default program, program_id is required.
  • Authentication: any API key or OAuth connection — Read or Read + Write — from a user with the View partners permission.

Response:

{
  "referral_link_id": "uuid",
  "referral_url": "https://partnertracker.soundgtm.com/r/AbCd1234",
  "status": "pending"
}

Unlike re-POSTing to register, GET is strictly read-only — it never reactivates a revoked partner, so it's safe to call any time.

Error statuses

On failure both methods return one of these status codes with a JSON { "error": "..." } body; the two answers with no body are under the table:

StatusPOSTGET
400Missing or invalid email (over 254 characters is invalid), name over 200 characters, a non-blank program_id string that isn't a UUID, or malformed JSON bodyMissing or invalid email (over 254 characters is invalid), a non-blank program_id that isn't a UUID, or no program_id and no default program in your account
401Missing, invalid, revoked or expired credential, or one whose user can't be foundSame as POST
403The credential isn't Read + Write (an OAuth connection approved as Read counts: ask for read_write), its user lacks the Invite referral partners permission, the credential belongs to a referral-partner account rather than a company, or your plan's partner limit has been reached (only the limit case carries upgrade fields such as upgradeRequired and upgradeToTier in the body)The credential's user lacks the View partners permission, or the credential belongs to a referral-partner account rather than a company
404The program_id doesn't exist in your accountThe program_id doesn't exist in your account, no link exists for that email and program, or the link has no referral URL yet (an older invite: register that partner with POST to generate one). The error message says which
422The target program isn't fully set up (for example, it's missing a payout rule or an enabled lead source), or no program_id was given and your account has no default program — finish configuring the program, then retryNot used: GET doesn't check that a program is set up
503A temporary database read failed, including the check of the program's readiness; this call created and changed nothing — safe to retryA temporary database read failed; it says nothing about whether the link exists — safe to retry
500The credential or its account type couldn't be read; the link couldn't be saved; or the link was saved but its referral URL couldn't be generated. All are safe to retry: after that last case a retry that succeeds returns the same link with 200 and uses no further partner-limit slotThe credential or its account type couldn't be read — safe to retry

Either method can also answer 500 with no JSON body if something fails that the route doesn't handle; that is safe to retry too. PUT, PATCH and DELETE get 405, also with no JSON body.

API reference | SoundGTM