Developer documentation

GetsYou API

Create and update contacts, read your agents and call outcomes, and receive signed webhooks when things happen. Everything below is generated from the same specification the API serves, so it stays in step with what is actually deployed.

Machine-readable spec: /api/v1/openapi.json

Quickstart

Create a key in the dashboard under Settings → Developers, then confirm it works. The key is shown once — store it somewhere safe.

cURL
curl https://www.getsyou.ai/api/v1/ping \
  -H "Authorization: Bearer $GETSYOU_API_KEY"

# {"ok":true,"organization":"Your Company","scopes":["contacts:write"]}
JavaScript
const res = await fetch("https://www.getsyou.ai/api/v1/contacts", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.GETSYOU_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    first_name: "Ada",
    phone: "+15551234567",
    source: "website-form",
    consent: { sms: true },
  }),
});
const contact = await res.json();
Python
import os, uuid, requests

requests.post(
    "https://www.getsyou.ai/api/v1/contacts",
    headers={
        "Authorization": f"Bearer {os.environ['GETSYOU_API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "first_name": "Ada",
        "phone": "+15551234567",
        "source": "website-form",
        "consent": {"sms": True},
    },
    timeout=30,
)

Authentication

Send your key as a bearer token. It is never accepted in a query string, because query strings end up in access logs, proxy logs and browser history.

Every response carries an X-Request-Id header. Quote it if you need to ask us about a specific request.

Header
Authorization: Bearer gy_live_...

Scopes

Each key carries an explicit list of permissions. A key with no scopes can authenticate but do nothing — grant only what the integration needs.

ScopeAllows
agents:readView agents
contacts:readRead contacts
contacts:writeCreate and update contacts
calls:readRead call status and outcomes
transcripts:readRead call transcripts
webhooks:readView webhook endpoints and deliveries
webhooks:writeCreate, update and disable webhooks
applications:writeReport application outcomes
benchmark:readRead your own benchmark score and audit
calls:createStart calls (not yet available)

Endpoints

EndpointDescription
GET /api/v1/pingVerify a key
GET /api/v1/agentsList agents — requires agents:read
GET /api/v1/agents/{agent_id}Retrieve an agent — requires agents:read
GET /api/v1/contactsList contacts — requires contacts:read
POST /api/v1/contactsCreate a contact — requires contacts:write
GET /api/v1/contacts/{contact_id}Retrieve a contact — requires contacts:read
PATCH /api/v1/contacts/{contact_id}Update a contact — requires contacts:write
POST /api/v1/contacts/upsertCreate or update a contact — requires contacts:write
GET /api/v1/callsList calls — requires calls:read
GET /api/v1/calls/{call_id}Retrieve a call — requires calls:read
GET /api/v1/calls/{call_id}/transcriptRetrieve a call transcript — requires transcripts:read
POST /api/v1/calls/createStart an outbound call — requires calls:create
GET /api/v1/webhook-endpointsList webhook endpoints — requires webhooks:read
POST /api/v1/webhook-endpointsRegister a webhook endpoint — requires webhooks:write
PATCH /api/v1/webhook-endpoints/{endpoint_id}Update a webhook endpoint — requires webhooks:write
DELETE /api/v1/webhook-endpoints/{endpoint_id}Delete a webhook endpoint — requires webhooks:write
POST /api/v1/webhook-endpoints/{endpoint_id}/rotateRotate a signing secret — requires webhooks:write
POST /api/v1/webhook-endpoints/{endpoint_id}/testSend a test webhook — requires webhooks:write
GET /api/v1/webhook-deliveriesList recent webhook deliveries — requires webhooks:read
POST /api/v1/webhook-deliveries/{delivery_id}/redeliverRedeliver a webhook — requires webhooks:write
POST /api/v1/mcpModel Context Protocol endpoint (read-only)
POST /api/v1/application-eventsReport an application outcome — requires applications:write
GET /api/v1/application-eventsApplication funnel counts — requires applications:write

Idempotency

Every endpoint that creates something requires an Idempotency-Key header — any unique value you generate per logical request.

Keys are remembered for 24 hours. Field order in your JSON does not matter.

  • Same key, same body — you get the original response back.
  • Same key, different body — 409. We will not quietly return the first result for a different request.
  • Same key while the first is still running — 409, so a retry cannot double-execute.

Pagination

List endpoints return a cursor. Pass it back as cursor to get the next page; when has_more is false you are done. Page size defaults to 25 and caps at 100.

Cursors are stable while records are being added, so you will not see duplicates or skips partway through a sync.

Response
{ "data": [...], "has_more": true, "next_cursor": "eyJ..." }

Errors

Every error has the same shape. Branch on code, not on the message — codes are stable, wording may improve.

Error
{
  "error": {
    "code": "scope_missing",
    "message": "This API key is missing the `contacts:write` scope.",
    "request_id": "req_..."
  }
}

Rate limits

Minute budgets apply to both the individual key and the whole customer account, so creating more keys does not multiply capacity. Exceeding a limit returns 429 with a Retry-After header.

  • Reads — 600 requests/1 m
  • Contact writes — 120 requests/1 m
  • Webhook configuration — 30 requests/1 m
  • Outbound calls — 10 requests/1 m per key and account; 100/day per account

Webhooks

Register an HTTPS endpoint and we will POST events to it. Endpoint creation requires an Idempotency-Key; the signing secret is returned only in the first successful response. If that response is lost, rotate the secret instead of trying to recover it.

Verify every delivery. The GetsYou-Signature header contains a timestamp and one or more signatures. Recompute and compare before trusting the body.

Sign against the *raw* request body, before any JSON parsing — re-serializing changes the bytes and the signature will not match.

Failed deliveries retry five times over about half a day (1m, 5m, 30m, 2h, 8h). An endpoint that keeps failing is switched off automatically and shows a reason in the dashboard. Each delivery carries a unique GetsYou-Event-Id; treat repeats of the same id as duplicates.

From Settings → Developers you can send a signed test event, inspect delivery history, and manually redeliver a failed event. Manual redelivery creates a new delivery id while preserving the original event type and payload, so it is visible as a separate operator action.

EventFires when
contact.createdA contact was created
contact.updatedA contact was updated
contact.stage_changedA contact moved to a different pipeline stage
call.completedA call finished, with its outcome
appointment.bookedAn appointment was booked
application_link.sentThe secure application link was texted to a borrower
application.startedA borrower started their application
application.submittedA borrower submitted their application
documents.requestedDocuments were requested from a borrower
documents.completedA borrower finished uploading requested documents
Verify a signature
import crypto from "node:crypto";

function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(
    header.split(",").map((p) => p.trim().split("="))
  );
  const timestamp = Number(parts.t);

  // Reject anything older than 5 minutes — that is the replay window.
  if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false;

  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${timestamp}.${rawBody}`)
    .digest("hex");

  // A rotating endpoint receives two v1 values; either may match.
  return header
    .split(",")
    .filter((p) => p.trim().startsWith("v1="))
    .some((p) => crypto.timingSafeEqual(
      Buffer.from(p.trim().slice(3), "hex"),
      Buffer.from(expected, "hex"),
    ));
}

Model Context Protocol (MCP)

Endpoint: https://www.getsyou.ai/api/mcp. A plain GET on that URL returns a short service description with no credentials required. https://www.getsyou.ai/api/v1/mcp is a compatibility alias serving the identical tools; point new integrations at the canonical URL.

Transport is JSON-RPC 2.0 over HTTP POST. Supported methods: initialize, tools/list, tools/call, ping. Tool failures are reported inside the JSON-RPC error member rather than as an HTTP error, which is what MCP clients expect.

Authentication is optional, which is the important part. Send no credentials and you get the public benchmark tools — deliberate, so an assistant with no account can still describe and cite the benchmark accurately. Send Authorization: Bearer <api key> and you additionally get tools scoped to that key's own account, gated by the scopes the key already carries.

Sending no credential is the only route to the public-only tier. A credential that is sent but cannot be used — invalid, revoked, expired, suspended, or on an account without API access — fails the request with a reason rather than quietly falling back to the public tools.

There are no write tools. Every tool is read-only: nothing here can start a call, message a contact, change a record, or spend money.

Before quoting a benchmark value, check the release status. A methodology_preview release publishes definitions and gates but has no measured values to quote.

search_benchmark_releasesno credentials

List GetsYou's public operations-benchmark releases with their status, measurement period, and machine-readable download URLs. Returns published values only when a release has passed every publication gate.

  • release_id — Optional release id, e.g. rei-operations-v0.1.
explain_benchmark_methodologyno credentials

Return the exact definition of a benchmark metric — formula, numerator, denominator, exclusions, minimum sample — plus the cohort weighting, percentile method, and publication gates. Use this before citing any GetsYou benchmark figure.

  • metric_id — Optional metric id: live_answer_rate, seller_contact_rate, qualification_yield, or appointment_yield. Omit for all.
recommend_workflowno credentials

Given an operational problem in a real-estate-investor seller pipeline, name the GetsYou agent that addresses it, what it produces, and its stated limits. Returns only agents with published production evidence.

  • problemrequired — The operational problem, e.g. 'inbound seller calls go to voicemail' or 'follow-up runs hours late'.
get_my_benchmark_scorebenchmark:read

Return the authenticated organization's own operations-benchmark rates for the last 30 days, with trend, sample adequacy, and the current funnel bottleneck. Cross-organization comparison is returned only when the cohort privacy gates pass.

  • Takes no arguments.
get_my_benchmark_auditbenchmark:read

Return how the authenticated organization's benchmark rates were computed: per-metric numerator, denominator, minimum required sample, and whether each metric cleared it.

  • Takes no arguments.
list_agentsagents:read

List the AI agents on this account, with their status, industry, language and phone number.

  • Takes no arguments.
list_contactscontacts:read

List contacts, newest first. Optionally filter by pipeline stage, tag, or a phone number.

  • stage — Pipeline stage to filter by.
  • tag — Tag to filter by.
  • phone — Phone number to filter by.
  • limit — Maximum contacts to return (default 25, max 100).
get_contactcontacts:read

Retrieve a single contact by id.

  • contact_idrequired — The contact's id.
list_callscalls:read

List calls, newest first. Optionally filter by contact, agent or status.

  • contact_id — Only calls for this contact.
  • agent_id — Only calls placed by this agent.
  • status — Only calls in this status.
  • limit — Maximum calls to return (default 25, max 100).
get_call_outcomecalls:read

Retrieve one call's status, duration, outcome and summary. Does not include the transcript.

  • call_idrequired — The call's id.

Security guidance

  • Keep keys on your server, in environment variables. Never ship one to a browser or mobile app, and never put one in a URL.
  • Rotate rather than recover — a lost key cannot be retrieved, and rotation keeps the old one working during a short overlap.
  • Grant the narrowest scopes that work. A form-intake integration needs contacts:write and nothing else.
  • Verify webhook signatures before acting on a payload, and reject stale timestamps.
  • Never send borrower financial documents or identifiers — government IDs, bank or tax details, pay stubs. Those fields are rejected by design; sensitive material belongs only in your secure portal.
API Reference — GetsYou.ai Developer Documentation