API reference

Connections

CRM and calendar connections

MethodPathSummary
GET/v1/account/connectionsThe connector catalog and the account's connections
POST/v1/account/connectionsSave a connection: its health check must pass first; the token goes to Vault
POST/v1/account/connections/mcpUse a tool server as the CRM or calendar: map each step to an approved tool. The read-only checks must pass first
POST/v1/account/connections/oauth/confirmFinish a sign-in to connect a CRM or calendar, with the token the callback handed the browser. Only the person who started it can (ADR 0111)
POST/v1/account/connections/oauth/startStart signing in to connect a CRM or calendar, or to reconnect one. Returns where to send the browser
POST/v1/account/connections/sandbox-link"Open sandbox CRM": a short-lived sign-in link to the account sandbox
DELETE/v1/account/connections/{connectionId}Delete a connection that no playbook uses (the sandbox stays)
POST/v1/account/connections/{connectionId}/guided-testWrite to the real system to prove the mapping: create a test contact, book the first open time and cancel it. Only when a member confirms
POST/v1/account/connections/{connectionId}/inbound-secretMake a new secret for signing requests your system sends to this connection’s webhook URL (v2, ADR 0112). Shown once; the previous one stops working
PUT/v1/account/connections/{connectionId}/mcpChange a tool server connection's mapping. The read-only checks must pass first
POST/v1/account/connections/{connectionId}/testRun the health check and record the result
GET/v1/account/rep-calendarsWhich members have connected their own calendar, by their sign-in email

The connector catalog and the account's connections#

GET /v1/account/connections

Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).

Response 200

FieldTypeRequiredDescription
catalogarray<ConnectorManifest>Yes—
catalog[].authenumYesOne of: "api_token", "oauth", "webhook_secret", "tool_connection", "none".
catalog[].connectorstringYes—
catalog[].descriptionstringYes—
catalog[].displayNamestringYes—
catalog[].dynamicRolesbooleanYes—
catalog[].optionsarray<object>Yes—
catalog[].options[].keystringYes—
catalog[].options[].labelstringYes—
catalog[].options[].requiredbooleanNo—
catalog[].options[].typeenumYesOne of: "string", "number", "boolean".
catalog[].rolesarray<enum>YesItems: "crm", "scheduler".
catalog[].signInWithstring | nullYes—
connectionsarray<Connection>Yes—
connections[].configmapYes—
connections[].config.{key}anyNoAny key.
connections[].connectorstringYes—
connections[].connectorNamestringYes—
connections[].createdAtstring (date-time)Yes—
connections[].hasSecretbooleanYes—
connections[].idstring (conn_… ID)YesID (conn_…)
connections[].inboundSecretAtstring (date-time) | nullYes—
connections[].inboundSignedAtstring (date-time) | nullYes—
connections[].kindenumYesOne of: "sandbox", "live".
connections[].lastCheckedAtstring (date-time) | nullYes—
connections[].lastErrorstring | nullYes—
connections[].namestringYes—
connections[].priceSyncbooleanYes—
connections[].rolesarray<enum>YesItems: "crm", "scheduler".
connections[].statusenumYesOne of: "connected", "error", "pending".
connections[].updatedAtstring (date-time)Yes—
connections[].warningsarray<string>Yes—

Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.

Example

bash
curl -X GET "$ANSWERSTACK_API_URL/v1/account/connections" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Save a connection: its health check must pass first; the token goes to Vault#

POST /v1/account/connections

Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).

Request body

application/json, required.

FieldTypeRequiredDescription
configobjectNoDefault: \{\}.
config.baseUrlstring (uri)NoUp to 500 characters.
config.{key}string | number | booleanNoAny key.
connectorstringYesPattern: ^[a-z][a-z0-9_]\{1,40\}$.
namestringYes1–120 characters.
tokenstringNo1–4000 characters.

Response 201

FieldTypeRequiredDescription
connectionConnectionYes—
connection.configmapYes—
connection.config.{key}anyNoAny key.
connection.connectorstringYes—
connection.connectorNamestringYes—
connection.createdAtstring (date-time)Yes—
connection.hasSecretbooleanYes—
connection.idstring (conn_… ID)YesID (conn_…)
connection.inboundSecretAtstring (date-time) | nullYes—
connection.inboundSignedAtstring (date-time) | nullYes—
connection.kindenumYesOne of: "sandbox", "live".
connection.lastCheckedAtstring (date-time) | nullYes—
connection.lastErrorstring | nullYes—
connection.namestringYes—
connection.priceSyncbooleanYes—
connection.rolesarray<enum>YesItems: "crm", "scheduler".
connection.statusenumYesOne of: "connected", "error", "pending".
connection.updatedAtstring (date-time)Yes—
connection.warningsarray<string>Yes—
healthobjectYes—
health.latencyMsnumberYes—
health.messagestringNo—
health.okbooleanYes—

Errors: 400, 401, 403, 404, 409, 422, 429, 500, with an ErrorBody body.

Example

bash
curl -X POST "$ANSWERSTACK_API_URL/v1/account/connections" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "connector": "string",
  "name": "string"
}'

Use a tool server as the CRM or calendar: map each step to an approved tool. The read-only checks must pass first#

POST /v1/account/connections/mcp

Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).

Request body

application/json, required.

FieldTypeRequiredDescription
methodsmapYes—
methods.{key}objectNoAny key.
methods.{key}.argsmapNoDefault: \{\}.
methods.{key}.args.{key}string | number | boolean | nullNoAny key.
methods.{key}.resultmapNoDefault: \{\}.
methods.{key}.result.{key}string | objectNoAny key.
methods.{key}.toolstringYes1–128 characters.
namestringYes1–120 characters.
toolConnectionIdstring (tcn_… ID)YesID (tcn_…)

Response 201

FieldTypeRequiredDescription
checksarray<ConnectionCheck>Yes—
checks[].checkstringYes—
checks[].detailstringYes—
checks[].okbooleanYes—
connectionConnectionYes—
connection.configmapYes—
connection.config.{key}anyNoAny key.
connection.connectorstringYes—
connection.connectorNamestringYes—
connection.createdAtstring (date-time)Yes—
connection.hasSecretbooleanYes—
connection.idstring (conn_… ID)YesID (conn_…)
connection.inboundSecretAtstring (date-time) | nullYes—
connection.inboundSignedAtstring (date-time) | nullYes—
connection.kindenumYesOne of: "sandbox", "live".
connection.lastCheckedAtstring (date-time) | nullYes—
connection.lastErrorstring | nullYes—
connection.namestringYes—
connection.priceSyncbooleanYes—
connection.rolesarray<enum>YesItems: "crm", "scheduler".
connection.statusenumYesOne of: "connected", "error", "pending".
connection.updatedAtstring (date-time)Yes—
connection.warningsarray<string>Yes—

Errors: 400, 401, 403, 404, 409, 422, 429, 500, with an ErrorBody body.

Example

bash
curl -X POST "$ANSWERSTACK_API_URL/v1/account/connections/mcp" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "string",
  "toolConnectionId": "tcn_2ZPh7XbT0v9Ao4iJ3qK1mN8sRgE",
  "methods": {}
}'

Finish a sign-in to connect a CRM or calendar, with the token the callback handed the browser. Only the person who started it can (ADR 0111)#

POST /v1/account/connections/oauth/confirm

Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).

Request body

application/json, required.

FieldTypeRequiredDescription
confirmstringYes20–200 characters.

Response 200

FieldTypeRequiredDescription
connectionstringNo—
reasonenumNoOne of: "unauthorized", "forbidden", "not_found", "rate_limited", "unavailable", "timeout", "misconfigured", "missing_permissions", "calendar_not_found", "calendar_read_only", "personal_account", "mailbox_access_denied", "failed".
resultenumYesOne of: "ok", "denied", "expired", "missing_scopes", "failed", "error", "wrong_user", "other_account".

Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.

Example

bash
curl -X POST "$ANSWERSTACK_API_URL/v1/account/connections/oauth/confirm" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "confirm": "string"
}'

Start signing in to connect a CRM or calendar, or to reconnect one. Returns where to send the browser#

POST /v1/account/connections/oauth/start

Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).

Request body

application/json, required.

FieldTypeRequiredDescription
configmapNo(variant 1) Default: \{\}.
config.{key}string | number | booleanNo(variant 1) Any key.
connectorstringYes(variant 1) Pattern: ^[a-z][a-z0-9_]\{1,40\}$.
namestringYes(variant 1) 1–120 characters.
connectionIdstring (conn_… ID)Yes(variant 2) ID (conn_…)

Response 200

FieldTypeRequiredDescription
authorizationUrlstringYes—
expiresInSecondsintegerYes—

Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.

Example

bash
curl -X POST "$ANSWERSTACK_API_URL/v1/account/connections/oauth/start" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "connector": "string",
  "name": "string"
}'

"Open sandbox CRM": a short-lived sign-in link to the account sandbox#

POST /v1/account/connections/sandbox-link

Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).

Response 200

FieldTypeRequiredDescription
expiresInSecondsintegerYes—
urlstringYes—

Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.

Example

bash
curl -X POST "$ANSWERSTACK_API_URL/v1/account/connections/sandbox-link" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Delete a connection that no playbook uses (the sandbox stays)#

DELETE /v1/account/connections/{connectionId}

Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).

Path parameters

NameTypeRequiredDescription
connectionIdstring (conn_… ID)YesID (conn_…)

Response 200

FieldTypeRequiredDescription
deletedenumYesOne of: true.

Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.

Example

bash
curl -X DELETE "$ANSWERSTACK_API_URL/v1/account/connections/{connectionId}" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Write to the real system to prove the mapping: create a test contact, book the first open time and cancel it. Only when a member confirms#

POST /v1/account/connections/{connectionId}/guided-test

Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).

Path parameters

NameTypeRequiredDescription
connectionIdstring (conn_… ID)YesID (conn_…)

Request body

application/json, required.

FieldTypeRequiredDescription
confirmenumYesOne of: true.
groupIdstring (grp_… ID)NoID (grp_…)

Response 200

FieldTypeRequiredDescription
checksarray<ConnectionCheck>Yes—
checks[].checkstringYes—
checks[].detailstringYes—
checks[].okbooleanYes—
okbooleanYes—

Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.

Example

bash
curl -X POST "$ANSWERSTACK_API_URL/v1/account/connections/{connectionId}/guided-test" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "confirm": true
}'

Make a new secret for signing requests your system sends to this connection’s webhook URL (v2, ADR 0112). Shown once; the previous one stops working#

POST /v1/account/connections/{connectionId}/inbound-secret

Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).

Path parameters

NameTypeRequiredDescription
connectionIdstring (conn_… ID)YesID (conn_…)

Response 200

FieldTypeRequiredDescription
connectionConnectionYes—
connection.configmapYes—
connection.config.{key}anyNoAny key.
connection.connectorstringYes—
connection.connectorNamestringYes—
connection.createdAtstring (date-time)Yes—
connection.hasSecretbooleanYes—
connection.idstring (conn_… ID)YesID (conn_…)
connection.inboundSecretAtstring (date-time) | nullYes—
connection.inboundSignedAtstring (date-time) | nullYes—
connection.kindenumYesOne of: "sandbox", "live".
connection.lastCheckedAtstring (date-time) | nullYes—
connection.lastErrorstring | nullYes—
connection.namestringYes—
connection.priceSyncbooleanYes—
connection.rolesarray<enum>YesItems: "crm", "scheduler".
connection.statusenumYesOne of: "connected", "error", "pending".
connection.updatedAtstring (date-time)Yes—
connection.warningsarray<string>Yes—
headerstringYes—
secretstringYes—
urlstringYes—

Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.

Example

bash
curl -X POST "$ANSWERSTACK_API_URL/v1/account/connections/{connectionId}/inbound-secret" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Change a tool server connection's mapping. The read-only checks must pass first#

PUT /v1/account/connections/{connectionId}/mcp

Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).

Path parameters

NameTypeRequiredDescription
connectionIdstring (conn_… ID)YesID (conn_…)

Request body

application/json, required.

FieldTypeRequiredDescription
methodsmapYes—
methods.{key}objectNoAny key.
methods.{key}.argsmapNoDefault: \{\}.
methods.{key}.args.{key}string | number | boolean | nullNoAny key.
methods.{key}.resultmapNoDefault: \{\}.
methods.{key}.result.{key}string | objectNoAny key.
methods.{key}.toolstringYes1–128 characters.
namestringYes1–120 characters.
toolConnectionIdstring (tcn_… ID)YesID (tcn_…)

Response 200

FieldTypeRequiredDescription
checksarray<ConnectionCheck>Yes—
checks[].checkstringYes—
checks[].detailstringYes—
checks[].okbooleanYes—
connectionConnectionYes—
connection.configmapYes—
connection.config.{key}anyNoAny key.
connection.connectorstringYes—
connection.connectorNamestringYes—
connection.createdAtstring (date-time)Yes—
connection.hasSecretbooleanYes—
connection.idstring (conn_… ID)YesID (conn_…)
connection.inboundSecretAtstring (date-time) | nullYes—
connection.inboundSignedAtstring (date-time) | nullYes—
connection.kindenumYesOne of: "sandbox", "live".
connection.lastCheckedAtstring (date-time) | nullYes—
connection.lastErrorstring | nullYes—
connection.namestringYes—
connection.priceSyncbooleanYes—
connection.rolesarray<enum>YesItems: "crm", "scheduler".
connection.statusenumYesOne of: "connected", "error", "pending".
connection.updatedAtstring (date-time)Yes—
connection.warningsarray<string>Yes—

Errors: 400, 401, 403, 404, 409, 422, 429, 500, with an ErrorBody body.

Example

bash
curl -X PUT "$ANSWERSTACK_API_URL/v1/account/connections/{connectionId}/mcp" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "string",
  "toolConnectionId": "tcn_2ZPh7XbT0v9Ao4iJ3qK1mN8sRgE",
  "methods": {}
}'

Run the health check and record the result#

POST /v1/account/connections/{connectionId}/test

Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).

Path parameters

NameTypeRequiredDescription
connectionIdstring (conn_… ID)YesID (conn_…)

Response 200

FieldTypeRequiredDescription
connectionConnectionYes—
connection.configmapYes—
connection.config.{key}anyNoAny key.
connection.connectorstringYes—
connection.connectorNamestringYes—
connection.createdAtstring (date-time)Yes—
connection.hasSecretbooleanYes—
connection.idstring (conn_… ID)YesID (conn_…)
connection.inboundSecretAtstring (date-time) | nullYes—
connection.inboundSignedAtstring (date-time) | nullYes—
connection.kindenumYesOne of: "sandbox", "live".
connection.lastCheckedAtstring (date-time) | nullYes—
connection.lastErrorstring | nullYes—
connection.namestringYes—
connection.priceSyncbooleanYes—
connection.rolesarray<enum>YesItems: "crm", "scheduler".
connection.statusenumYesOne of: "connected", "error", "pending".
connection.updatedAtstring (date-time)Yes—
connection.warningsarray<string>Yes—
healthobjectYes—
health.latencyMsnumberYes—
health.messagestringNo—
health.okbooleanYes—

Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.

Example

bash
curl -X POST "$ANSWERSTACK_API_URL/v1/account/connections/{connectionId}/test" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Which members have connected their own calendar, by their sign-in email#

GET /v1/account/rep-calendars

Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).

Response 200

FieldTypeRequiredDescription
calendarsarray<RepCalendarStatus>Yes—
calendars[].accountEmailstring | nullYes—
calendars[].lastCheckedAtstring (date-time) | nullYes—
calendars[].lastErrorstring | nullYes—
calendars[].providerstringYes—
calendars[].statusenumYesOne of: "connected", "error", "pending".
calendars[].userEmailstringYes—
calendars[].userIdstring (usr_… ID)YesID (usr_…)

Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.

Example

bash
curl -X GET "$ANSWERSTACK_API_URL/v1/account/rep-calendars" \
  -H "Authorization: Bearer $ACCESS_TOKEN"