Reference
Agent API reference
The API an embedded app or agent calls on a member's behalf, generated from its live OpenAPI document.
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.
| Route | Token | Scope |
|---|---|---|
| GET /api/v1/display | workspace | read |
| GET /api/v1/workspaces/{workspaceId}/display | workspace | read |
| GET /api/v1/me/board | workspace | read |
| GET /api/v1/workspaces | workspace | read |
| POST /api/v1/change-log | workspace | data:write |
| POST /api/v1/workspaces/{workspaceId}/change-log | workspace | data:write |
| POST /api/v1/workspaces/{workspaceId}/test-runs | workspace | test:run |
| GET /api/v1/workspaces/{workspaceId}/test-runs/{id} | workspace | test:run |
| POST /api/v1/forms/post-call | workspace | data:write |
| POST /api/v1/forms/past-call | workspace | data:write |
| POST /api/v1/forms/dm-close | workspace | data:write |
| POST /api/v1/forms/affiliate-sale | workspace | data:write |
| POST /api/v1/forms/eod | workspace | data:write |
| POST /api/v1/forms/drafts | workspace | data:write |
| GET /api/v1/forms/drafts | workspace | read |
| GET /api/v1/agency/workspaces | agency | read |
| POST /api/v1/plans | agency | config:plan (Pro plan) |
| GET /api/v1/plans/{id} | agency | config:plan |
| POST /api/v1/plans/{id}/apply | agency | config:apply (Pro plan) |
| POST /api/v1/plans/{id}/request-approval | agency | config:plan |
| GET /api/v1/templates | agency | read |
| GET /api/v1/templates/{key} | agency | read |
| PUT /api/v1/templates/{key} | agency | config:plan (Pro plan) |
| POST /api/v1/workspaces/{id}/connect-links | agency | connect:links |
| GET /api/v1/workspaces/{id}/connect-links/{linkId} | agency | connect:links |
| POST /api/v1/workspaces/{id}/connect-links/{linkId}/revoke | agency | connect:links |
| GET /api/v1/key-drops/providers | agency | connect:links |
| POST /api/v1/workspaces/{id}/key-drops | agency | connect:links |
| GET /api/v1/workspaces/{id}/key-drops/{dropId} | agency | connect:links |
| GET /api/v1/workspaces/{id}/keys | agency | connect:links |
| POST /api/v1/workspaces/{id}/keys/{provider}/test | agency | connect: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, connect links and key drops, 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused 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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
workspaceId | path | string | yes |
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused 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}/...
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused 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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key | header | string | yes | A 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin |
| 409 | A write with this Idempotency-Key is still running: refused.idempotency_in_progress |
| 422 | This 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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
workspaceId | path | string | yes | |
Idempotency-Key | header | string | yes | A 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin |
| 409 | A write with this Idempotency-Key is still running: refused.idempotency_in_progress |
| 422 | This Idempotency-Key was used for a different request: refused.idempotency_key_reused |
POST /api/v1/workspaces/{workspaceId}/test-runs
Run a test lead
Starts a simulated test lead: PYLO drives its own intake and stops before anything reaches a person, and every record it made is voided. A live run is refused here, because it files a real CRM lead and sends real messages; a person starts it in the app under Settings, Test lead.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
workspaceId | path | string | yes | |
Idempotency-Key | header | string | yes | A 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin |
| 409 | A write with this Idempotency-Key is still running: refused.idempotency_in_progress |
| 422 | This Idempotency-Key was used for a different request: refused.idempotency_key_reused |
GET /api/v1/workspaces/{workspaceId}/test-runs/{id}
A test lead run
One run and its trace: each step, what it sent and where, and what was voided afterwards.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
workspaceId | path | string | yes | |
id | path | string | yes |
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused 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/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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key | header | string | yes | A 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin |
| 409 | A write with this Idempotency-Key is still running: refused.idempotency_in_progress |
| 422 | This 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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key | header | string | yes | A 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin |
| 409 | A write with this Idempotency-Key is still running: refused.idempotency_in_progress |
| 422 | This 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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key | header | string | yes | A 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin |
| 409 | A write with this Idempotency-Key is still running: refused.idempotency_in_progress |
| 422 | This Idempotency-Key was used for a different request: refused.idempotency_key_reused |
POST /api/v1/forms/affiliate-sale
Log an affiliate sale
A signup the member made through the program's link. Merged with a sale already logged for the same buyer email or reference, so a second submission edits the first. Needs a member's session token; an API token is refused with refused.drafts_only.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key | header | string | yes | A 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin |
| 409 | A write with this Idempotency-Key is still running: refused.idempotency_in_progress |
| 422 | This 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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key | header | string | yes | A 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin |
| 409 | A write with this Idempotency-Key is still running: refused.idempotency_in_progress |
| 422 | This 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused 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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key | header | string | yes | A 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused with a machine readable reason: insufficient_scope, refused.member_scope, refused.drafts_only, refused.cross_workspace, refused.token_in_browser, refused.origin |
| 409 | A write with this Idempotency-Key is still running: refused.idempotency_in_progress |
| 422 | This 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused 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 Pro plan. A workspace token is refused with token.not_agency.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key | header | string | yes | A 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 402 | tier.upgrade_required: the agency is not on the Pro plan |
| 403 | Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope) |
| 409 | A write with this Idempotency-Key is still running: refused.idempotency_in_progress |
| 422 | This 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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes |
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused 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, or send approvalCode in the body, the code a person typed after a chat code request (pack 13). Reversible, hard to reverse and people and money plans need a person's approval under the workspace's policy even with config:apply. 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 Pro plan. A workspace token is refused with token.not_agency.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
Idempotency-Key | header | string | yes | A 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 402 | tier.upgrade_required: the agency is not on the Pro plan |
| 403 | Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope) |
| 409 | A write with this Idempotency-Key is still running: refused.idempotency_in_progress |
| 422 | This 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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
Idempotency-Key | header | string | yes | A 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope) |
| 409 | A write with this Idempotency-Key is still running: refused.idempotency_in_progress |
| 422 | This 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused 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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
key | path | string | yes |
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused 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 Pro plan. A workspace token is refused with token.not_agency.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
key | path | string | yes | |
Idempotency-Key | header | string | yes | A 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 402 | tier.upgrade_required: the agency is not on the Pro plan |
| 403 | Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope) |
| 409 | A write with this Idempotency-Key is still running: refused.idempotency_in_progress |
| 422 | This 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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
Idempotency-Key | header | string | yes | A 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope) |
| 409 | A write with this Idempotency-Key is still running: refused.idempotency_in_progress |
| 422 | This Idempotency-Key was used for a different request: refused.idempotency_key_reused |
GET /api/v1/workspaces/{id}/connect-links/{linkId}
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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
linkId | path | string | yes |
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused 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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
linkId | path | string | yes | |
Idempotency-Key | header | string | yes | A 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope) |
| 409 | A write with this Idempotency-Key is still running: refused.idempotency_in_progress |
| 422 | This Idempotency-Key was used for a different request: refused.idempotency_key_reused |
GET /api/v1/key-drops/providers
Tools a key can be dropped for
Each tool a key drop can collect a key for, the fields it asks for, and the .env names the PYLO CLI recognises for each. Needs an agency token (client_api_tokens kind='agency') with connect:links. A workspace token is refused with token.not_agency.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope) |
POST /api/v1/workspaces/{id}/key-drops
Make a key drop
Body { provider, fields? }. One drop for one tool on a workspace the agency holds, open for 15 minutes. Whoever holds it can hand PYLO the key without an account; PYLO stores it in the vault and tests it. Needs an agency token (client_api_tokens kind='agency') with connect:links. A workspace token is refused with token.not_agency.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
Idempotency-Key | header | string | yes | A 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope) |
| 409 | A write with this Idempotency-Key is still running: refused.idempotency_in_progress |
| 422 | This Idempotency-Key was used for a different request: refused.idempotency_key_reused |
GET /api/v1/workspaces/{id}/key-drops/{dropId}
A key drop's state
Whether the key arrived, whether its test passed or failed and why, and the account and scopes the test saw. Never the key. Needs an agency token (client_api_tokens kind='agency') with connect:links. A workspace token is refused with token.not_agency.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
dropId | path | string | yes |
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope) |
GET /api/v1/workspaces/{id}/keys
The workspace's keys
Each key the vault holds for the workspace, by name: whether it is present, its last test result and when, the account, and its expiry and rotate-by dates. Never the key. Needs an agency token (client_api_tokens kind='agency') with connect:links. A workspace token is refused with token.not_agency.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes |
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope) |
POST /api/v1/workspaces/{id}/keys/{provider}/test
Test a key
Runs the vault's test for one key against its tool and answers ok with the account, or what the tool said and the problem. Needs an agency token (client_api_tokens kind='agency') with connect:links. A workspace token is refused with token.not_agency.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
provider | path | string | yes | |
Idempotency-Key | header | string | yes | A 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.
| Response | Meaning |
|---|---|
| 200 | OK |
| 400 | Refused, with the field and the sentence: { error, field }. A write with no Idempotency-Key header is refused here with refused.idempotency_key_required. |
| 401 | No token, or not a PYLO token, or revoked |
| 403 | Refused with a machine readable reason: token.not_agency, scope.missing (with requiredScope) |
| 409 | A write with this Idempotency-Key is still running: refused.idempotency_in_progress |
| 422 | This Idempotency-Key was used for a different request: refused.idempotency_key_reused |