Chili Piper Handoff API

The handoff API from Chili Piper — 3 operation(s) for handoff.

OpenAPI Specification

chili-piper-handoff-api-openapi.yml Raw ↑
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: handoff
paths:
  /v1/org/handoff/routers/handoff/list:
    get:
      tags:
      - handoff
      summary: Lists all handoff routers
      description: "[operation: handoff-router-list]\n\n\n\nREAD-ONLY\n\n\n\nBrowses 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.\n\n→\n\n    [{id, workspaceId, name?, routing: {known, representable, rows: [{ruleId?, ruleType?, outcome}], catchAll?: {outcome}}}]\n\n  Note: the routing summary is fully populated and has the same lossy-by-design shape as handoff-router-get\n\nsee: 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:
      - handoff
      summary: Get handoff router
      description: "[operation: handoff-router-get]\n\n\n\nREAD-ONLY\n\n\n\nFetches 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).\n\n→\n\n    {id, workspaceId, name?, routing: {known, representable, rows: [{ruleId?, ruleType?, outcome}], catchAll?: {outcome}}}\n    outcome (one of): {type: \"Schedule\", distributionId?, userId?, meetingTypeId?} | {type: \"Redirect\", url?} | {type: \"OwnerAssign\"} | {type: \"ContactOptions\"} | {type: \"CrmAction\"} | {type: \"Other\", kind}\n\n  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\n\n  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).\n\nsee: 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:
      - handoff
      summary: Update handoff router
      description: "[operation: handoff-router-update]\n\n\n\nMUTATING — IDEMPOTENT\n\n\n\nEdits 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.\n\n- 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:\n\n    {routes: [{ruleId, outcome}], catchAll: outcome}\n\n  outcome:\n\n    {type: \"Schedule\", assignment, meetingTypeId, crmActions?}\n\n  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).\n\n  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).\n\n→\n\n    {id, workspaceId, name?, routing: {known, representable, rows: [{ruleId?, ruleType?, outcome}], catchAll?: {outcome}}}\n\n  Note: the returned routing is the lossy per-row summary (same shape as handoff-router-get), not the matrix you sent\n\n⚠ full-replace + publishes live immediately: supplying routing replaces the ENTIRE matrix, not a partial merge\n\n⚠ 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.\n\n⚠ 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\n\n⚠ 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\n\nsee: 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:
      - handoff
      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:
      - handoff
      summary: Create handoff router
      description: "[operation: handoff-router-create]\n\n\n\nMUTATING\n\n\n\nCreates 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:\n\n- 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:\n\n    {routes: [{ruleId, outcome}], catchAll: outcome}\n\n  outcome:\n\n    {type: \"Schedule\", assignment, meetingTypeId, crmActions?}\n\n  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).\n\n  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).\n\n→\n\n    {id, workspaceId, name?, routing: {known, representable, rows: [{ruleId?, ruleType?, outcome}], catchAll?: {outcome}}}\n\n  Note: the returned routing is the lossy per-row summary (same shape as handoff-router-get), not the matrix you sent\n\n⚠ 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\n\nsee: 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:
    RoutingCatchAllSummary:
      title: RoutingCatchAllSummary
      type: object
      required:
      - outcome
      properties:
        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'
    DistributionId:
      title: DistributionId
      examples:
      - 7f8a1b2c-3d4e-4f5a-8b9c-0d1e2f3a4b5c
      type: string
      pattern: '[^\s\\/]+'
    CrmAction_Notify:
      title: CrmAction_Notify
      type: object
      required:
      - type
      properties:
        slackChannel:
          type: string
        type:
          type: string
          const: Notify
    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'
    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'
    WorkspaceId:
      title: WorkspaceId
      examples:
      - b7263a5d-89cb-4f50-a532-ea4aff74688e
      type: string
      pattern: '[^\s\\/]+'
    RoutingOutcome_Redirect:
      title: RoutingOutcome_Redirect
      type: object
      required:
      - type
      properties:
        url:
          examples:
          - https://example.com
          type: string
        type:
          type: string
          const: Redirect
    RouterRouting:
      title: RouterRouting
      type: object
      required:
      - catchAll
      properties:
        routes:
          type: array
          items:
            $ref: '#/components/schemas/RouteRow'
        catchAll:
          $ref: '#/components/schemas/RouteOutcome'
    MeetingTypeId:
      title: MeetingTypeId
      examples:
      - 4a8f2b3c-7d1e-4f9b-8a2c-3d5e6f789012
      type: string
      format: uuid
    RoutingOutcome_Other:
      title: RoutingOutcome_Other
      type: object
      required:
      - kind
      - type
      properties:
        kind:
          type: string
        type:
          type: string
          const: Other
    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'
    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
    RoutingRowSummary:
      title: RoutingRowSummary
      type: object
      required:
      - outcome
      properties:
        ruleId:
          type: string
          pattern: '[^\s\\/]+'
        ruleType:
          type: string
        outcome:
          $ref: '#/components/schemas/RoutingOutcome'
    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'
    HandoffRouterUpdate:
      title: HandoffRouterUpdate
      type: object
      properties:
        name:
          type: string
        routing:
          $ref: '#/components/schemas/RouterRouting'
    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
    TimeoutRedirect_Url:
      title: TimeoutRedirect_Url
      type: object
      required:
      - url
      - type
      properties:
        url:
          examples:
          - https://example.com
          type: string
        type:
          type: string
          const: Url
    TimeoutRedirect_Landing:
      title: TimeoutRedirect_Landing
      type: object
      required:
      - type
      properties:
        type:
          type: string
          const: Landing
    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
    RoutingOutcome_OwnerAssign:
      title: RoutingOutcome_OwnerAssign
      type: object
      required:
      - type
      properties:
        type:
          type: string
          const: OwnerAssign
    RouteTimeout:
      title: RouteTimeout
      type: object
      required:
      - minutes
      - onTimeout
      properties:
        minutes:
          type: integer
          format: int32
        onTimeout:
          $ref: '#/components/schemas/TimeoutRedirect'
    HandoffRouterCreate:
      title: HandoffRouterCreate
      type: object
      required:
      - workspaceId
      - name
      - routing
      properties:
        workspaceId:
          $ref: '#/components/schemas/WorkspaceId'
        name:
          type: string
        routing:
          $ref: '#/components/schemas/RouterRouting'
    RoutingOutcome_ContactOptions:
      title: RoutingOutcome_ContactOptions
      type: object
      required:
      - type
      properties:
        type:
          type: string
          const: ContactOptions
    Map_String:
      title: Map_String
      type: object
      additionalProperties:
        type: string
    RouteOutcome_Redirect:
      title: RouteOutcome_Redirect
      type: object
      required:
      - url
      - type
      properties:
        url:
          examples:
          - https://example.com
          type: string
        type:
          type: string
          const: Redirect
    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'
    CrmAction_ConvertLead:
      title: CrmAction_ConvertLead
      type: object
      required:
      - type
      properties:
        type:
          type: string
          const: ConvertLead
    HandoffRouterId:
      title: HandoffRouterId
      examples:
      - e1f2a3b4-c5d6-4e7f-b8a9-0b1c2d3e4f5a
      type: string
      pattern: '[^\s\\/]+'
    RouteAssignment_Distribution:
      title: RouteAssignment_Distribution
      type: object
      required:
      - distributionId
      - type
      properties:
        distributionId:
          $ref: '#/components/schemas/DistributionId'
        type:
          type: string
          const: Distribution
    RoutingOutcome_CrmAction:
      title: RoutingOutcome_CrmAction
      type: object
      required:
      - type
      properties:
        type:
          type: string
          const: CrmAction
    UserId:
      title: UserId
      examples:
      - 64ee0722-c7c6-4b48-bc89-356c99f1d25d
      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'
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      description: 'API key in Authorization header. Format: ''Authorization: Bearer <api-key>'' — 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