PYLO Docs
Contents

Home and My Board

Leads

Webinars

Resources

Settings: Integrations and automations

Settings: Billing

Settings: Data

Reference

Agent API reference

The API an embedded app or agent calls on a member's behalf, generated from its live OpenAPI document.

Read as MarkdownGenerated from PYLO's live description of itself.

Generated from the live OpenAPI document at https://api.pylosystem.com/openapi/agent.json. It is the API an embedded app calls on behalf of a signed-in member; see Embedded apps.

Forms, drafts and display config, for agents and for web apps with PYLO behind them, and the agency API: plans, blueprints and connect links, on an agency token. PYLO is the source of truth: an embedded app keeps no sales data of its own.

Never put a workspace or agency token in a browser. Anyone using the page could take it and read the whole workspace, commission included, and PYLO refuses one presented from a web page (refused.token_in_browser). A web app signs its user in with PYLO (OAuth 2.1, authorization code with PKCE) and calls PYLO with that member's own session token, from an origin the workspace lists in Settings, Embedded apps.

RouteTokenScope
GET /api/v1/displayworkspaceread
GET /api/v1/workspaces/{workspaceId}/displayworkspaceread
GET /api/v1/me/boardworkspaceread
GET /api/v1/workspacesworkspaceread
POST /api/v1/change-logworkspacedata:write
POST /api/v1/workspaces/{workspaceId}/change-logworkspacedata:write
POST /api/v1/forms/post-callworkspacedata:write
POST /api/v1/forms/past-callworkspacedata:write
POST /api/v1/forms/dm-closeworkspacedata:write
POST /api/v1/forms/eodworkspacedata:write
POST /api/v1/forms/draftsworkspacedata:write
GET /api/v1/forms/draftsworkspaceread
GET /api/v1/agency/workspacesagencyread
POST /api/v1/plansagencyconfig:plan (Agency plan)
GET /api/v1/plans/{id}agencyconfig:plan
POST /api/v1/plans/{id}/applyagencyconfig:apply (Agency plan)
POST /api/v1/plans/{id}/request-approvalagencyconfig:plan
GET /api/v1/templatesagencyread
GET /api/v1/templates/{key}agencyread
PUT /api/v1/templates/{key}agencyconfig:plan (Agency plan)
POST /api/v1/workspaces/{id}/connect-linksagencyconnect:links
GET /api/v1/workspaces/{id}/connect-links/{linkId}agencyconnect:links
POST /api/v1/workspaces/{id}/connect-links/{linkId}/revokeagencyconnect:links

Base URL

  • https://api.pylosystem.com

Authentication

  • pyloOAuth: oauth2. Sign in with PYLO. Authorization code with PKCE (S256), the resource parameter set to https://api.pylosystem.com/api/v1. Discovery: https://api.pylosystem.com/.well-known/oauth-authorization-server.
  • bearer: HTTP bearer. A PYLO API token, for server-side agents only. Never put a workspace or agency token in a browser. Anyone using the page could take it and read the whole workspace, commission included, and PYLO refuses one presented from a web page (refused.token_in_browser). A web app signs its user in with PYLO (OAuth 2.1, authorization code with PKCE) and calls PYLO with that member's own session token, from an origin the workspace lists in Settings, Embedded apps.
  • agencyBearer: HTTP bearer. A PYLO agency token (client_api_tokens with kind='agency', made on Agency OS, Tokens), for server-side agents only. It reaches the agency's plans, blueprints and connect links, and no workspace's data. Scopes: read, config:plan, config:apply, connect:links. Never put a workspace or agency token in a browser. Anyone using the page could take it and read the whole workspace, commission included, and PYLO refuses one presented from a web page (refused.token_in_browser). A web app signs its user in with PYLO (OAuth 2.1, authorization code with PKCE) and calls PYLO with that member's own session token, from an origin the workspace lists in Settings, Embedded apps.

Endpoints

GET /api/v1/display

Display config

The workspace's name, logo, colours, labels, modules to show, programmes and currency code, so one template app can brand itself for any workspace.

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin

GET /api/v1/workspaces/{workspaceId}/display

Display config, by workspace

The same, naming the workspace: the form a template app uses, and the one an agency token must use.

ParameterInTypeRequiredDescription
workspaceIdpathstringyes
ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin

GET /api/v1/me/board

My board

The signed-in member's own board: the figures PYLO shows them on My Board. A closer's, setter's or SDR's token reads this and nothing workspace-wide. Needs a member's session token; an API token is refused with refused.drafts_only.

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin

GET /api/v1/workspaces

Workspaces

The workspaces this token reaches. An agency token names one in the path: /api/v1/workspaces/{id}/...

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin

POST /api/v1/change-log

Record a change

A dated entry saying what changed and why: a price, an offer, a script, a rule. Written against the token's own workspace. Read it back with listChanges, and compare the figures either side with compareAroundChange.

ParameterInTypeRequiredDescription
Idempotency-KeyheaderstringyesA value of 8 to 200 characters, unique to this write. Send the same one when you retry: the first answer is returned again rather than the write being done twice.

Request body: object.

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin
409A write with this Idempotency-Key is still running: refused.idempotency_in_progress
422This Idempotency-Key was used for a different request: refused.idempotency_key_reused

POST /api/v1/workspaces/{workspaceId}/change-log

Record a change, by workspace

The same, naming the workspace: the form an agency token must use, since it reaches more than one.

ParameterInTypeRequiredDescription
workspaceIdpathstringyes
Idempotency-KeyheaderstringyesA value of 8 to 200 characters, unique to this write. Send the same one when you retry: the first answer is returned again rather than the write being done twice.

Request body: object.

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin
409A write with this Idempotency-Key is still running: refused.idempotency_in_progress
422This Idempotency-Key was used for a different request: refused.idempotency_key_reused

POST /api/v1/forms/post-call

File a post-call form

The app's own post-call form, with the app's own validation: the same errors, field by field. Filed as the signed-in member, on a call they hold a slot on. Idempotent on submission_id. Needs a member's session token; an API token is refused with refused.drafts_only.

ParameterInTypeRequiredDescription
Idempotency-KeyheaderstringyesA value of 8 to 200 characters, unique to this write. Send the same one when you retry: the first answer is returned again rather than the write being done twice.

Request body: object.

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin
409A write with this Idempotency-Key is still running: refused.idempotency_in_progress
422This Idempotency-Key was used for a different request: refused.idempotency_key_reused

POST /api/v1/forms/past-call

Log a past call

A call that happened with no booking in PYLO, with its form. Idempotent on submission_id. Needs a member's session token; an API token is refused with refused.drafts_only.

ParameterInTypeRequiredDescription
Idempotency-KeyheaderstringyesA value of 8 to 200 characters, unique to this write. Send the same one when you retry: the first answer is returned again rather than the write being done twice.

Request body: object.

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin
409A write with this Idempotency-Key is still running: refused.idempotency_in_progress
422This Idempotency-Key was used for a different request: refused.idempotency_key_reused

POST /api/v1/forms/dm-close

Log a DM close

A sale made over messages, with no call. Idempotent on submission_id. Needs a member's session token; an API token is refused with refused.drafts_only.

ParameterInTypeRequiredDescription
Idempotency-KeyheaderstringyesA value of 8 to 200 characters, unique to this write. Send the same one when you retry: the first answer is returned again rather than the write being done twice.

Request body: object.

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin
409A write with this Idempotency-Key is still running: refused.idempotency_in_progress
422This Idempotency-Key was used for a different request: refused.idempotency_key_reused

POST /api/v1/forms/eod

File an end of day report

The member's own EOD. One per member per day: a second submission edits the first. Needs a member's session token; an API token is refused with refused.drafts_only.

ParameterInTypeRequiredDescription
Idempotency-KeyheaderstringyesA value of 8 to 200 characters, unique to this write. Send the same one when you retry: the first answer is returned again rather than the write being done twice.

Request body: object.

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin
409A write with this Idempotency-Key is still running: refused.idempotency_in_progress
422This Idempotency-Key was used for a different request: refused.idempotency_key_reused

GET /api/v1/forms/drafts

Open drafts

Open drafts. A closer, setter or SDR sees their own.

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin

POST /api/v1/forms/drafts

Propose a draft

An agent proposes a form, for example a post-call form from a transcript, for a member to check and file. A draft never carries money: one with a cash, revenue, payment or instalment field is refused (refused.cash_figures). Idempotent on the Idempotency-Key header.

ParameterInTypeRequiredDescription
Idempotency-KeyheaderstringyesA value of 8 to 200 characters, unique to this write. Send the same one when you retry: the first answer is returned again rather than the write being done twice.

Request body: object.

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin
409A write with this Idempotency-Key is still running: refused.idempotency_in_progress
422This Idempotency-Key was used for a different request: refused.idempotency_key_reused

GET /api/v1/agency/workspaces

The agency's workspaces

Every workspace the agency holds and has not archived: id, name, slug, currency, status and when it was made, so an agent can name one in a plan or a connect link. Needs an agency token (client_api_tokens kind='agency') with read. A workspace token is refused with token.not_agency.

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope)

POST /api/v1/plans

Draft a plan

Describe a workspace to create or change (settings, team, programmes, integrations to connect) and get back the plan: every change PYLO would make, what is blocked and why. Nothing is changed. Needs an agency token (client_api_tokens kind='agency') with config:plan, on the Agency plan or above. A workspace token is refused with token.not_agency.

ParameterInTypeRequiredDescription
Idempotency-KeyheaderstringyesA value of 8 to 200 characters, unique to this write. Send the same one when you retry: the first answer is returned again rather than the write being done twice.

Request body: object.

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
402tier.upgrade_required: the agency is not on the Agency plan or above
403Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope)
409A write with this Idempotency-Key is still running: refused.idempotency_in_progress
422This Idempotency-Key was used for a different request: refused.idempotency_key_reused

GET /api/v1/plans/{id}

A plan

A plan and its state: drafted, waiting for approval, approved, applied, or refused with the reason. Needs an agency token (client_api_tokens kind='agency') with config:plan. A workspace token is refused with token.not_agency.

ParameterInTypeRequiredDescription
idpathstringyes
ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope)

POST /api/v1/plans/{id}/apply

Apply a plan

Make the plan's changes. Idempotent on the Idempotency-Key header: a retry answers the first result. Without config:apply it is refused with requiredScope config:apply and approval "request": ask for approval instead. Tokens a plan issues for new members come back once, here. Needs an agency token (client_api_tokens kind='agency') with config:apply, on the Agency plan or above. A workspace token is refused with token.not_agency.

ParameterInTypeRequiredDescription
idpathstringyes
Idempotency-KeyheaderstringyesA value of 8 to 200 characters, unique to this write. Send the same one when you retry: the first answer is returned again rather than the write being done twice.

Request body: object.

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
402tier.upgrade_required: the agency is not on the Agency plan or above
403Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope)
409A write with this Idempotency-Key is still running: refused.idempotency_in_progress
422This Idempotency-Key was used for a different request: refused.idempotency_key_reused

POST /api/v1/plans/{id}/request-approval

Ask a person to approve a plan

For a token without config:apply. A person approves or declines the plan in the app. Needs an agency token (client_api_tokens kind='agency') with config:plan. A workspace token is refused with token.not_agency.

ParameterInTypeRequiredDescription
idpathstringyes
Idempotency-KeyheaderstringyesA value of 8 to 200 characters, unique to this write. Send the same one when you retry: the first answer is returned again rather than the write being done twice.

Request body: object.

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope)
409A write with this Idempotency-Key is still running: refused.idempotency_in_progress
422This Idempotency-Key was used for a different request: refused.idempotency_key_reused

GET /api/v1/templates

Blueprints

The agency's blueprints: saved workspace shapes a plan can start from. Needs an agency token (client_api_tokens kind='agency') with read. A workspace token is refused with token.not_agency.

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope)

GET /api/v1/templates/{key}

A blueprint

One blueprint by its key. Needs an agency token (client_api_tokens kind='agency') with read. A workspace token is refused with token.not_agency.

ParameterInTypeRequiredDescription
keypathstringyes
ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope)

PUT /api/v1/templates/{key}

Save a blueprint

Create or replace a blueprint under its key. Needs an agency token (client_api_tokens kind='agency') with config:plan, on the Agency plan or above. A workspace token is refused with token.not_agency.

ParameterInTypeRequiredDescription
keypathstringyes
Idempotency-KeyheaderstringyesA value of 8 to 200 characters, unique to this write. Send the same one when you retry: the first answer is returned again rather than the write being done twice.

Request body: object.

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
402tier.upgrade_required: the agency is not on the Agency plan or above
403Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope)
409A write with this Idempotency-Key is still running: refused.idempotency_in_progress
422This Idempotency-Key was used for a different request: refused.idempotency_key_reused

POST /api/v1/workspaces/{id}/connect-links

Make a connect link

A link a client opens to connect one integration to a workspace the agency holds, without an account. The response carries the link once. Needs an agency token (client_api_tokens kind='agency') with connect:links. A workspace token is refused with token.not_agency.

ParameterInTypeRequiredDescription
idpathstringyes
Idempotency-KeyheaderstringyesA value of 8 to 200 characters, unique to this write. Send the same one when you retry: the first answer is returned again rather than the write being done twice.

Request body: object.

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope)
409A write with this Idempotency-Key is still running: refused.idempotency_in_progress
422This Idempotency-Key was used for a different request: refused.idempotency_key_reused

A connect link's state

When the link expires, whether it was revoked or completed, and each integration it offers with its state. Never the link itself or any credential. Needs an agency token (client_api_tokens kind='agency') with connect:links. A workspace token is refused with token.not_agency.

ParameterInTypeRequiredDescription
idpathstringyes
linkIdpathstringyes
ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope)

POST /api/v1/workspaces/{id}/connect-links/{linkId}/revoke

Revoke a connect link

The link stops opening. A connection it already made stays. Needs an agency token (client_api_tokens kind='agency') with connect:links. A workspace token is refused with token.not_agency.

ParameterInTypeRequiredDescription
idpathstringyes
linkIdpathstringyes
Idempotency-KeyheaderstringyesA value of 8 to 200 characters, unique to this write. Send the same one when you retry: the first answer is returned again rather than the write being done twice.

Request body: object.

ResponseMeaning
200OK
400Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required.
401No token, or not a PYLO token, or revoked
403Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope)
409A write with this Idempotency-Key is still running: refused.idempotency_in_progress
422This Idempotency-Key was used for a different request: refused.idempotency_key_reused