openapi: 3.2.0 info: title: Chili Piper — Router Configuration Actions Handoff API version: 1.287.2 description: GPT Actions for the handoff-router-configuration GPT — a subset of the Chili Piper Edge API. Authenticate with a Bearer API key (Admin Center → API Keys). servers: - url: https://fire.chilipiper.com/api/fire-edge description: Production security: - apiKeyAuth: [] tags: - name: Hand off paths: /v1/org/handoff/routers/handoff/list: get: tags: - Hand off summary: Lists all handoff routers description: '[operation: handoff-router-list] READ-ONLY Browses Handoff routers to discover routerIds and see what each one routes. A Handoff router routes SDR-to-AE handoffs to teams/users via rules. Each entry carries the router''s identity plus a lossy per-row summary of its routing. Pass workspaceId to restrict to one workspace (must belong to this tenant); omit it to fan out across all workspaces. → [{id, workspaceId, name?, routing: {known, representable, rows: [{ruleId?, ruleType?, outcome}], catchAll?: {outcome}}}] Note: the routing summary is fully populated and has the same lossy-by-design shape as handoff-router-get see: workspace-list (find a workspaceId), handoff-router-get (fetch one), handoff-router-update (replace config)' operationId: handoffRouterList parameters: - name: workspaceId in: query description: Filter handoff routers by workspace ID. Omit to list across all of the tenant's workspaces. required: false schema: type: string pattern: '[^\s\\/]+' responses: '200': description: '' headers: Cache-Control: required: true schema: type: string X-Robots-Tag: required: true schema: type: string Pragma: required: true schema: type: string Expires: required: true schema: type: string content: application/json: schema: type: array items: $ref: '#/components/schemas/HandoffRouter' '400': description: 'Invalid value for: query parameter workspaceId' content: text/plain: schema: type: string default: description: '' headers: Location: required: false schema: type: string content: application/json: schema: type: object required: - errorCode - errorMessage properties: errorCode: type: string errorMessage: type: string arguments: $ref: '#/components/schemas/Map_String' security: - apiKeyAuth: [] X-Chili-Required-Permissions: - handoff.read /v1/org/handoff/routers/handoff/{routerId}: get: tags: - Hand off summary: Get handoff router description: '[operation: handoff-router-get] READ-ONLY Fetches one Handoff router: its identity plus a lossy per-row summary of what its routing does. Call this before handoff-router-update to check whether the router''s routing is representable (safe to replace via the API). → {id, workspaceId, name?, routing: {known, representable, rows: [{ruleId?, ruleType?, outcome}], catchAll?: {outcome}}} outcome (one of): {type: "Schedule", distributionId?, userId?, meetingTypeId?} | {type: "Redirect", url?} | {type: "OwnerAssign"} | {type: "ContactOptions"} | {type: "CrmAction"} | {type: "Other", kind} Note: the summary is lossy by design — it NAMES each row''s outcome (including ones Edge can''t itself produce) so you can see what the router does even when it was built in the app Note: routing.representable is true only when the current routing — both the draft tree and the published tree — is exactly what Edge''s create/update would have produced; when false, an update with a new routing may be rejected (edit it in the Handoff app instead). A router that has no routing tree yet also reports representable=false, but an update setting routing on it is still accepted (nothing is destroyed). see: handoff-router-list (browse to find a routerId), handoff-router-update (replace routing if representable)' operationId: handoffRouterGet parameters: - name: routerId in: path required: true schema: type: string pattern: '[^\s\\/]+' responses: '200': description: '' headers: Cache-Control: required: true schema: type: string X-Robots-Tag: required: true schema: type: string Pragma: required: true schema: type: string Expires: required: true schema: type: string content: application/json: schema: $ref: '#/components/schemas/HandoffRouter' '400': description: 'Invalid value for: path parameter routerId' content: text/plain: schema: type: string default: description: '' headers: Location: required: false schema: type: string content: application/json: schema: type: object required: - errorCode - errorMessage properties: errorCode: type: string errorMessage: type: string arguments: $ref: '#/components/schemas/Map_String' security: - apiKeyAuth: [] X-Chili-Required-Permissions: - handoff.read put: tags: - Hand off summary: Update handoff router description: '[operation: handoff-router-update] MUTATING — IDEMPOTENT Edits a Handoff router and republishes it live. Only the fields you supply change; omitted fields are preserved. Use handoff-router-get first to confirm the routing is representable before replacing it. - routing (opt): when present, fully REPLACES the routing matrix (not a partial merge); when omitted, the current routing is kept. Each row''s rule, when it matches, runs that row''s `outcome`; the catch-all `outcome` runs when no row matches: {routes: [{ruleId, outcome}], catchAll: outcome} outcome: {type: "Schedule", assignment, meetingTypeId, crmActions?} Schedule assigns the lead and books a meeting type. assignment is {type: "Distribution", distributionId} or {type: "User", userId}. crmActions (opt) is an ordered post-booking chain, each {type: "ConvertLead"}. ruleId is required on every row; an always-match route is the catchAll. routes may be empty (then only the catchAll applies). Note: handoff routers support only Schedule outcomes — no Redirect, no no-show timeout, and ConvertLead is the only CRM action (concierge routers support the full set). Supplying any of those is rejected (400). → {id, workspaceId, name?, routing: {known, representable, rows: [{ruleId?, ruleType?, outcome}], catchAll?: {outcome}}} Note: the returned routing is the lossy per-row summary (same shape as handoff-router-get), not the matrix you sent ⚠ full-replace + publishes live immediately: supplying routing replaces the ENTIRE matrix, not a partial merge ⚠ REJECTED (409) when the router''s existing routing — its DRAFT tree or its PUBLISHED tree — isn''t representable in this simplified model (advanced routing built in the Handoff app) — to avoid silently destroying it, edit those routers in the Handoff app instead. Check routing.representable via handoff-router-get first. A name-only update (no routing) always succeeds. ⚠ every update publishes the router''s current DRAFT — if the draft carries unpublished edits made in the Handoff app, those go live as a side effect, even on a name-only patch ⚠ if the final publish step fails, the changes are saved on an UNPUBLISHED draft and a typed 422 error is returned — fix or delete the draft in the Handoff app see: handoff-router-get (check routing.representable before replacing), rule-list (find ruleIds), distribution-list (find distributionIds), user-find (find userIds), meeting-type-list (find meetingTypeIds)' operationId: handoffRouterUpdate parameters: - name: routerId in: path required: true schema: type: string pattern: '[^\s\\/]+' requestBody: content: application/json: schema: $ref: '#/components/schemas/HandoffRouterUpdate' required: true responses: '200': description: '' headers: Cache-Control: required: true schema: type: string X-Robots-Tag: required: true schema: type: string Pragma: required: true schema: type: string Expires: required: true schema: type: string content: application/json: schema: $ref: '#/components/schemas/HandoffRouter' '400': description: 'Invalid value for: path parameter routerId, Invalid value for: body' content: text/plain: schema: type: string default: description: '' headers: Location: required: false schema: type: string content: application/json: schema: type: object required: - errorCode - errorMessage properties: errorCode: type: string errorMessage: type: string arguments: $ref: '#/components/schemas/Map_String' security: - apiKeyAuth: [] X-Chili-Required-Permissions: - handoff.modify delete: tags: - Hand off summary: Remove handoff router description: '[operation: handoff-router-delete] MUTATING — DESTRUCTIVE Permanently deletes a Handoff router. ⚠ irreversible via API; any links or integrations pointing at this router stop working see: handoff-router-list or handoff-router-get (confirm the id before deleting)' operationId: handoffRouterDelete parameters: - name: routerId in: path required: true schema: type: string pattern: '[^\s\\/]+' responses: '200': description: '' headers: Cache-Control: required: true schema: type: string X-Robots-Tag: required: true schema: type: string Pragma: required: true schema: type: string Expires: required: true schema: type: string '400': description: 'Invalid value for: path parameter routerId' content: text/plain: schema: type: string default: description: '' headers: Location: required: false schema: type: string content: application/json: schema: type: object required: - errorCode - errorMessage properties: errorCode: type: string errorMessage: type: string arguments: $ref: '#/components/schemas/Map_String' security: - apiKeyAuth: [] X-Chili-Required-Permissions: - handoff.remove /v1/org/handoff/routers/handoff: post: tags: - Hand off summary: Create handoff router description: '[operation: handoff-router-create] MUTATING Creates a Handoff router and publishes it live in one step — there is no unpublished-draft state via the API. workspaceId must be a team workspace of this tenant (400 otherwise). The routing matrix is a list of ordered rules evaluated top-down plus a mandatory catch-all fallback: - routing (req): ordered rules evaluated top-down, plus a mandatory catch-all fallback. Each row''s rule, when it matches, runs that row''s `outcome`; the catch-all `outcome` runs when no row matches: {routes: [{ruleId, outcome}], catchAll: outcome} outcome: {type: "Schedule", assignment, meetingTypeId, crmActions?} Schedule assigns the lead and books a meeting type. assignment is {type: "Distribution", distributionId} (round-robin / ownership / whatever the distribution does) or {type: "User", userId} (a specific host). crmActions (opt) is an ordered post-booking chain, each {type: "ConvertLead"}. ruleId is required on every row; an always-match route is the catchAll. routes may be empty (then only the catchAll applies). Note: handoff routers support only Schedule outcomes — no Redirect, no no-show timeout, and ConvertLead is the only CRM action (concierge routers support the full set). Supplying any of those is rejected (400). → {id, workspaceId, name?, routing: {known, representable, rows: [{ruleId?, ruleType?, outcome}], catchAll?: {outcome}}} Note: the returned routing is the lossy per-row summary (same shape as handoff-router-get), not the matrix you sent ⚠ if the final publish step fails the router is left behind as an UNPUBLISHED draft (typed 422); retrying the create mints ANOTHER draft — fix or delete the leftover in the Handoff app see: handoff-router-list (find a workspaceId), rule-list (find ruleIds), distribution-list (find distributionIds), user-find (find userIds), meeting-type-list (find meetingTypeIds), handoff-router-update (replace config afterwards)' operationId: handoffRouterCreate requestBody: content: application/json: schema: $ref: '#/components/schemas/HandoffRouterCreate' required: true responses: '200': description: '' headers: Cache-Control: required: true schema: type: string X-Robots-Tag: required: true schema: type: string Pragma: required: true schema: type: string Expires: required: true schema: type: string content: application/json: schema: $ref: '#/components/schemas/HandoffRouter' '400': description: 'Invalid value for: body' content: text/plain: schema: type: string default: description: '' headers: Location: required: false schema: type: string content: application/json: schema: type: object required: - errorCode - errorMessage properties: errorCode: type: string errorMessage: type: string arguments: $ref: '#/components/schemas/Map_String' security: - apiKeyAuth: [] X-Chili-Required-Permissions: - handoff.create components: schemas: RouterRouting: title: RouterRouting type: object required: - catchAll properties: routes: type: array items: $ref: '#/components/schemas/RouteRow' catchAll: $ref: '#/components/schemas/RouteOutcome' HandoffRouterUpdate: title: HandoffRouterUpdate type: object properties: name: type: string routing: $ref: '#/components/schemas/RouterRouting' TimeoutRedirect: title: TimeoutRedirect oneOf: - $ref: '#/components/schemas/TimeoutRedirect_Landing' - $ref: '#/components/schemas/TimeoutRedirect_Url' discriminator: propertyName: type mapping: Landing: '#/components/schemas/TimeoutRedirect_Landing' Url: '#/components/schemas/TimeoutRedirect_Url' RoutingOutcome_Redirect: title: RoutingOutcome_Redirect type: object required: - type properties: url: examples: - https://example.com type: string type: type: string const: Redirect HandoffRouterId: title: HandoffRouterId examples: - e1f2a3b4-c5d6-4e7f-b8a9-0b1c2d3e4f5a type: string pattern: '[^\s\\/]+' RouteRow: title: RouteRow type: object required: - outcome properties: ruleId: type: string pattern: '[^\s\\/]+' outcome: $ref: '#/components/schemas/RouteOutcome' RouteAssignment_User: title: RouteAssignment_User type: object required: - userId - type properties: userId: $ref: '#/components/schemas/UserId' type: type: string const: User RoutingRowSummary: title: RoutingRowSummary type: object required: - outcome properties: ruleId: type: string pattern: '[^\s\\/]+' ruleType: type: string outcome: $ref: '#/components/schemas/RoutingOutcome' RouteAssignment: title: RouteAssignment oneOf: - $ref: '#/components/schemas/RouteAssignment_Distribution' - $ref: '#/components/schemas/RouteAssignment_User' discriminator: propertyName: type mapping: Distribution: '#/components/schemas/RouteAssignment_Distribution' User: '#/components/schemas/RouteAssignment_User' RouteTimeout: title: RouteTimeout type: object required: - minutes - onTimeout properties: minutes: type: integer format: int32 onTimeout: $ref: '#/components/schemas/TimeoutRedirect' RouteOutcome: title: RouteOutcome oneOf: - $ref: '#/components/schemas/RouteOutcome_Redirect' - $ref: '#/components/schemas/RouteOutcome_Schedule' discriminator: propertyName: type mapping: Redirect: '#/components/schemas/RouteOutcome_Redirect' Schedule: '#/components/schemas/RouteOutcome_Schedule' RoutingOutcome_OwnerAssign: title: RoutingOutcome_OwnerAssign type: object required: - type properties: type: type: string const: OwnerAssign RoutingOutcome_Schedule: title: RoutingOutcome_Schedule type: object required: - type properties: distributionId: type: string pattern: '[^\s\\/]+' userId: type: string pattern: '[^\s\\/]+' meetingTypeId: type: string format: uuid type: type: string const: Schedule RoutingCatchAllSummary: title: RoutingCatchAllSummary type: object required: - outcome properties: outcome: $ref: '#/components/schemas/RoutingOutcome' RoutingOutcome_Other: title: RoutingOutcome_Other type: object required: - kind - type properties: kind: type: string type: type: string const: Other TimeoutRedirect_Url: title: TimeoutRedirect_Url type: object required: - url - type properties: url: examples: - https://example.com type: string type: type: string const: Url WorkspaceId: title: WorkspaceId examples: - b7263a5d-89cb-4f50-a532-ea4aff74688e type: string pattern: '[^\s\\/]+' RoutingOutcome_CrmAction: title: RoutingOutcome_CrmAction type: object required: - type properties: type: type: string const: CrmAction CrmAction_ConvertLead: title: CrmAction_ConvertLead type: object required: - type properties: type: type: string const: ConvertLead MeetingTypeId: title: MeetingTypeId examples: - 4a8f2b3c-7d1e-4f9b-8a2c-3d5e6f789012 type: string format: uuid TimeoutRedirect_Landing: title: TimeoutRedirect_Landing type: object required: - type properties: type: type: string const: Landing UserId: title: UserId examples: - 64ee0722-c7c6-4b48-bc89-356c99f1d25d type: string pattern: '[^\s\\/]+' RouteOutcome_Schedule: title: RouteOutcome_Schedule type: object required: - assignment - meetingTypeId - type properties: assignment: $ref: '#/components/schemas/RouteAssignment' meetingTypeId: $ref: '#/components/schemas/MeetingTypeId' timeout: $ref: '#/components/schemas/RouteTimeout' crmActions: type: array items: $ref: '#/components/schemas/CrmAction' type: type: string const: Schedule RouteOutcome_Redirect: title: RouteOutcome_Redirect type: object required: - url - type properties: url: examples: - https://example.com type: string type: type: string const: Redirect RouteAssignment_Distribution: title: RouteAssignment_Distribution type: object required: - distributionId - type properties: distributionId: $ref: '#/components/schemas/DistributionId' type: type: string const: Distribution CrmAction_Notify: title: CrmAction_Notify type: object required: - type properties: slackChannel: type: string type: type: string const: Notify HandoffRouter: title: HandoffRouter type: object required: - id - workspaceId - routing properties: id: $ref: '#/components/schemas/HandoffRouterId' workspaceId: $ref: '#/components/schemas/WorkspaceId' name: type: string routing: $ref: '#/components/schemas/RouterRoutingSummary' RoutingOutcome_ContactOptions: title: RoutingOutcome_ContactOptions type: object required: - type properties: type: type: string const: ContactOptions RouterRoutingSummary: title: RouterRoutingSummary type: object required: - known - representable properties: known: type: boolean representable: type: boolean rows: type: array items: $ref: '#/components/schemas/RoutingRowSummary' catchAll: $ref: '#/components/schemas/RoutingCatchAllSummary' Map_String: title: Map_String type: object additionalProperties: type: string DistributionId: title: DistributionId examples: - 7f8a1b2c-3d4e-4f5a-8b9c-0d1e2f3a4b5c type: string pattern: '[^\s\\/]+' RoutingOutcome: title: RoutingOutcome oneOf: - $ref: '#/components/schemas/RoutingOutcome_ContactOptions' - $ref: '#/components/schemas/RoutingOutcome_CrmAction' - $ref: '#/components/schemas/RoutingOutcome_Other' - $ref: '#/components/schemas/RoutingOutcome_OwnerAssign' - $ref: '#/components/schemas/RoutingOutcome_Redirect' - $ref: '#/components/schemas/RoutingOutcome_Schedule' discriminator: propertyName: type mapping: ContactOptions: '#/components/schemas/RoutingOutcome_ContactOptions' CrmAction: '#/components/schemas/RoutingOutcome_CrmAction' Other: '#/components/schemas/RoutingOutcome_Other' OwnerAssign: '#/components/schemas/RoutingOutcome_OwnerAssign' Redirect: '#/components/schemas/RoutingOutcome_Redirect' Schedule: '#/components/schemas/RoutingOutcome_Schedule' HandoffRouterCreate: title: HandoffRouterCreate type: object required: - workspaceId - name - routing properties: workspaceId: $ref: '#/components/schemas/WorkspaceId' name: type: string routing: $ref: '#/components/schemas/RouterRouting' CrmAction: title: CrmAction oneOf: - $ref: '#/components/schemas/CrmAction_ConvertLead' - $ref: '#/components/schemas/CrmAction_Notify' discriminator: propertyName: type mapping: ConvertLead: '#/components/schemas/CrmAction_ConvertLead' Notify: '#/components/schemas/CrmAction_Notify' securitySchemes: apiKeyAuth: type: apiKey description: 'API key in Authorization header. Format: ''Authorization: Bearer '' — the word ''Bearer'' followed by a space and the key is required. Sending the key without the Bearer prefix returns 401.' name: Authorization in: header