> ## Documentation Index
> Fetch the complete documentation index at: https://docs.open.cx/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect Front

> Generate an API token, enter credentials, select the AI teammate, and configure the webhook.

export const FrontFlow = () => {
  const BEAM_COLOR = "#22c55e";
  const renderBeam = ({id, d, duration = 2.8, delay = 0, reverse = false}) => {
    const values = reverse ? {
      x1: "110%;-10%",
      x2: "120%;0%"
    } : {
      x1: "-10%;110%",
      x2: "0%;120%"
    };
    return <g key={id}>
        <path d={d} stroke="currentColor" strokeOpacity="0.18" strokeWidth="1.5" fill="none" strokeLinecap="round" />
        <path d={d} stroke={`url(#${id})`} strokeWidth="2" fill="none" strokeLinecap="round" />
        <defs>
          <linearGradient id={id} gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="0" y2="0">
            <stop offset="0%" stopColor={BEAM_COLOR} stopOpacity="0" />
            <stop offset="45%" stopColor={BEAM_COLOR} stopOpacity="1" />
            <stop offset="55%" stopColor={BEAM_COLOR} stopOpacity="1" />
            <stop offset="100%" stopColor={BEAM_COLOR} stopOpacity="0" />
            <animate attributeName="x1" values={values.x1} dur={`${duration}s`} begin={`${delay}s`} repeatCount="indefinite" />
            <animate attributeName="x2" values={values.x2} dur={`${duration}s`} begin={`${delay}s`} repeatCount="indefinite" />
          </linearGradient>
        </defs>
      </g>;
  };
  const CH_X = 90, FRONT_X = 440, OCX_X = 780;
  const MID = 180, R = 44, CHR = 22;
  const channels = [{
    key: "email",
    label: "Email",
    y: 80
  }, {
    key: "sms",
    label: "SMS",
    y: 135
  }, {
    key: "chat",
    label: "Chat",
    y: 225
  }, {
    key: "call",
    label: "Call",
    y: 280
  }];
  const beams = channels.map((ch, i) => ({
    id: `fr-ch-${i}`,
    d: `M ${CH_X + CHR},${ch.y} C ${CH_X + CHR + 120},${ch.y} ${FRONT_X - R - 120},${MID} ${FRONT_X - R},${MID}`,
    delay: i * 0.3
  }));
  const bMain = `M ${FRONT_X + R},${MID} C ${FRONT_X + 140},${MID - 30} ${OCX_X - 140},${MID - 30} ${OCX_X - R},${MID}`;
  const bMainRev = `M ${FRONT_X + R},${MID} C ${FRONT_X + 140},${MID + 30} ${OCX_X - 140},${MID + 30} ${OCX_X - R},${MID}`;
  return <div className="zendesk-flow not-prose my-8 w-full">
      <div className="zendesk-flow-frame relative w-full overflow-hidden rounded-md border border-black/10 bg-white px-4 py-6 dark:border-white/10 dark:bg-zinc-950">
        <div className="zendesk-flow-grid pointer-events-none absolute inset-0" aria-hidden />
        <svg viewBox="0 0 880 360" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" className="relative z-[1] block w-full text-zinc-500 dark:text-zinc-400" role="img" aria-label="Front flow: four message types route into Front; OpenCX shows up as a dedicated teammate alongside human teammates">
          {beams.map(b => renderBeam({
    id: b.id,
    d: b.d,
    duration: 3.2,
    delay: b.delay
  }))}
          {renderBeam({
    id: "fr-m",
    d: bMain,
    duration: 2.6,
    delay: 0
  })}
          {renderBeam({
    id: "fr-mr",
    d: bMainRev,
    duration: 2.6,
    delay: 1.3,
    reverse: true
  })}

          {}
          {channels.map(ch => <g key={ch.key}>
              <circle cx={CH_X} cy={ch.y} r={CHR} className="fill-white stroke-black/10 dark:fill-zinc-900 dark:stroke-white/10" strokeWidth="1" />
              <g transform={`translate(${CH_X - 7} ${ch.y - 7})`} className="text-zinc-700 dark:text-zinc-200">
                {ch.key === "email" && <g fill="currentColor"><path d="M2 3h12a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1Zm0 1.5v.3l6 3.6 6-3.6v-.3H2Z" /></g>}
                {ch.key === "sms" && <g fill="currentColor"><path d="M3 1.5A1.5 1.5 0 0 0 1.5 3v8A1.5 1.5 0 0 0 3 12.5h2V15l2.8-2.5H13A1.5 1.5 0 0 0 14.5 11V3A1.5 1.5 0 0 0 13 1.5H3Zm1 4.75a.75.75 0 1 1 1.5 0 .75.75 0 0 1-1.5 0Zm3.25 0a.75.75 0 1 1 1.5 0 .75.75 0 0 1-1.5 0Zm3.25 0a.75.75 0 1 1 1.5 0 .75.75 0 0 1-1.5 0Z" /></g>}
                {ch.key === "chat" && <g fill="currentColor"><path d="M1 2.5A1.5 1.5 0 0 1 2.5 1h11A1.5 1.5 0 0 1 15 2.5v7A1.5 1.5 0 0 1 13.5 11H9l-3 3v-3H2.5A1.5 1.5 0 0 1 1 9.5v-7z" /></g>}
                {ch.key === "call" && <svg x="0" y="0" width="14" height="14" viewBox="0 0 20 20" fill="currentColor">
                    <path d="M2 3.5A1.5 1.5 0 0 1 3.5 2h1.148a1.5 1.5 0 0 1 1.465 1.175l.716 3.223a1.5 1.5 0 0 1-1.052 1.767l-.933.267c-.41.117-.643.555-.48.95a11.5 11.5 0 0 0 6.254 6.254c.395.163.833-.07.95-.48l.267-.933a1.5 1.5 0 0 1 1.767-1.052l3.223.716A1.5 1.5 0 0 1 18 14.352V15.5a1.5 1.5 0 0 1-1.5 1.5H15c-1.149 0-2.263-.15-3.326-.43A13.022 13.022 0 0 1 2.43 7.326 13.019 13.019 0 0 1 2 4V3.5Z" />
                  </svg>}
              </g>
              <text x={CH_X + CHR + 8} y={ch.y + 4} className="fill-zinc-700 dark:fill-zinc-200" style={{
    font: "500 11px ui-sans-serif, system-ui, sans-serif"
  }}>{ch.label}</text>
            </g>)}

          <text x={CH_X} y={45} textAnchor="middle" className="fill-zinc-500 dark:fill-zinc-400" style={{
    font: "500 10.5px ui-sans-serif, system-ui, sans-serif"
  }}>message types</text>

          {}
          <g>
            <circle cx={FRONT_X} cy={MID} r={R} className="fill-white stroke-black/10 dark:fill-zinc-900 dark:stroke-white/10" strokeWidth="1" />
            <foreignObject x={FRONT_X - 22} y={MID - 22} width="44" height="44">
              <div className="flex h-full w-full items-center justify-center">
                <img src="/images/integrations/front.svg" alt="" className="h-8 w-8 object-contain" />
              </div>
            </foreignObject>
            <text x={FRONT_X} y={MID + R + 22} textAnchor="middle" className="fill-zinc-700 dark:fill-zinc-200" style={{
    font: "600 12px ui-sans-serif, system-ui, sans-serif"
  }}>Front</text>
            <text x={FRONT_X} y={MID + R + 36} textAnchor="middle" className="fill-zinc-500 dark:fill-zinc-400" style={{
    font: "400 10.5px ui-sans-serif, system-ui, sans-serif"
  }}>shared inbox</text>
          </g>

          <text x={(FRONT_X + OCX_X) / 2} y={MID - 46} textAnchor="middle" className="fill-zinc-500 dark:fill-zinc-400" style={{
    font: "500 11px ui-sans-serif, system-ui, sans-serif"
  }}>reply as teammate</text>
          <text x={(FRONT_X + OCX_X) / 2} y={MID + 54} textAnchor="middle" className="fill-zinc-500 dark:fill-zinc-400" style={{
    font: "500 11px ui-sans-serif, system-ui, sans-serif"
  }}>handoff · unassign</text>

          {}
          <g>
            {}
            <g>
              <circle cx={OCX_X + 30} cy={MID - 40} r="14" className="fill-white stroke-black/10 dark:fill-zinc-900 dark:stroke-white/10" strokeWidth="1" />
              <circle cx={OCX_X + 40} cy={MID - 30} r="14" className="fill-white stroke-black/10 dark:fill-zinc-900 dark:stroke-white/10" strokeWidth="1" />
              <g transform={`translate(${OCX_X + 30 - 6} ${MID - 40 - 7})`} className="fill-none stroke-zinc-600 dark:stroke-zinc-300" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round">
                <circle cx="6" cy="5" r="2.5" />
                <path d="M 1 13 C 1 9 11 9 11 13" />
              </g>
              <g transform={`translate(${OCX_X + 40 - 6} ${MID - 30 - 7})`} className="fill-none stroke-zinc-600 dark:stroke-zinc-300" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round">
                <circle cx="6" cy="5" r="2.5" />
                <path d="M 1 13 C 1 9 11 9 11 13" />
              </g>
            </g>

            <circle cx={OCX_X} cy={MID} r={R + 4} className="fill-none" stroke={BEAM_COLOR} strokeOpacity="0.25" strokeWidth="1.5">
              <animate attributeName="r" values={`${R + 2};${R + 12};${R + 2}`} dur="3.6s" repeatCount="indefinite" />
              <animate attributeName="stroke-opacity" values="0.35;0;0.35" dur="3.6s" repeatCount="indefinite" />
            </circle>
            <circle cx={OCX_X} cy={MID} r={R} className="fill-white stroke-black/10 dark:fill-zinc-900 dark:stroke-white/10" strokeWidth="1" />
            <foreignObject x={OCX_X - 34} y={MID - 18} width="68" height="36">
              <div className="flex h-full w-full items-center justify-center">
                <img src="/logo-light.svg" alt="" className="block h-full w-full object-contain dark:hidden" />
                <img src="/logo.svg" alt="" className="hidden h-full w-full object-contain dark:block" />
              </div>
            </foreignObject>
            <text x={OCX_X} y={MID + R + 22} textAnchor="middle" className="fill-zinc-700 dark:fill-zinc-200" style={{
    font: "600 12px ui-sans-serif, system-ui, sans-serif"
  }}>OpenCX</text>
            <text x={OCX_X} y={MID + R + 36} textAnchor="middle" className="fill-zinc-500 dark:fill-zinc-400" style={{
    font: "400 10.5px ui-sans-serif, system-ui, sans-serif"
  }}>AI · teammate identity</text>
          </g>
        </svg>
      </div>
    </div>;
};

One-time setup: enter your Front API token, pick the <Tooltip tip="A user account in Front. OpenCX posts AI replies as this teammate so customers see a consistent identity.">teammate</Tooltip> the AI replies as, paste a webhook URL into Front, and choose whether the AI handles unassigned conversations.

<FrontFlow />

<Info>
  This page covers the shared Front connection. Once connected, see the [channel pages](/integrations/front/channels/email) for per-channel verification steps.
</Info>

## Before you start

<AccordionGroup>
  <Accordion title="Front workspace with API access" icon="key">
    You need a Front workspace on a plan that includes API access. You also need permissions to generate API tokens in **Settings → Developers → API tokens**.
  </Accordion>

  <Accordion title="Admin access in OpenCX" icon="shield-check">
    Only organization admins can connect integrations. Confirm your role at [**Settings → Organization**](https://platform.open.cx/settings).
  </Accordion>
</AccordionGroup>

## Setup

<Steps>
  <Step title="Generate an API token in Front">
    In Front, go to [**Settings → Developers → API tokens**](https://app.frontapp.com/settings/developers/tokens). Create a new token with the following scopes:

    * **Shared Resources** — read and write
    * **Private Resources** — read and write
    * **Provisioning** — read

    <Warning>
      Store the token securely — Front only shows it once. If you lose it, revoke and regenerate.
    </Warning>
  </Step>

  <Step title="Enter the API token in OpenCX">
    Open [**Settings → Ticketing System**](https://platform.open.cx/settings/ticketing) in your OpenCX dashboard. Select **Front** and enter your API token.

    Click **Connect**. OpenCX validates the token by calling the Front API. If validation fails, double-check the token has not been revoked and your Front plan includes API access.
  </Step>

  <Step title="Select the AI teammate">
    After credentials are saved, OpenCX loads your Front teammates. Pick the teammate account that represents the AI — this is who customers see replies from.

    <Warning>
      Every AI-generated reply is posted as this teammate. Choose a dedicated bot account (e.g. "AI Agent") rather than a real team member to avoid confusion.
    </Warning>
  </Step>

  <Step title="Copy the webhook URL">
    OpenCX displays a webhook URL after connection. Copy it and configure it in your Front app's [webhook settings](https://dev.frontapp.com/docs/webhooks-1).

    The webhook needs to receive these event types:

    | Event                     | Why OpenCX needs it                                        |
    | ------------------------- | ---------------------------------------------------------- |
    | **Inbound message**       | Process new customer messages and generate AI replies.     |
    | **Outbound message**      | Detect teammate replies so the AI doesn't re-process them. |
    | **Conversation archived** | Sync resolved status back to the OpenCX session.           |

    <Warning>
      Without the webhook, OpenCX cannot receive conversation events. The AI will not respond to any messages until the webhook is active.
    </Warning>
  </Step>

  <Step title="Configure unassigned handling (optional)">
    Enable **Handle unassigned conversations** if you want the AI to respond to conversations that arrive without an assignee. When disabled, the AI only responds to conversations assigned to the selected teammate.
  </Step>

  <Step title="Send a test message">
    Send a test message through one of your Front channels. The AI should reply within a few seconds. Then say *"I want to talk to a human"* — you should see a handoff note appear as an internal comment and the conversation unassigned.

    <Info>
      For channel-specific verification, see the [Channels](/integrations/front/channels/email) pages.
    </Info>
  </Step>
</Steps>

## Settings reference

All settings are configured at [**Settings → Ticketing System**](https://platform.open.cx/settings/ticketing) → Front.

| Setting                             | Purpose                                                                                 |
| ----------------------------------- | --------------------------------------------------------------------------------------- |
| **API token**                       | Your Front API token from Developer Settings. Required.                                 |
| **AI teammate**                     | The Front teammate the AI replies as. Required for targeted routing.                    |
| **Handle unassigned conversations** | When enabled, the AI also responds to conversations with no assignee. Default: off.     |
| **Enabled**                         | Master toggle for the Front integration. When disabled, all webhook events are ignored. |

## Disconnecting

To remove the Front integration, open [**Settings → Ticketing System**](https://platform.open.cx/settings/ticketing) → Front and click **Disconnect**. This deletes stored credentials, resets your ticketing system to OpenCX's built-in inbox, and stops webhook processing. Existing OpenCX sessions are preserved but no longer sync with Front.

***

## Related Documentation

<CardGroup cols={2}>
  <Card title="Conversations" icon="messages" href="/integrations/front/conversations">
    How messages flow, handoff steps, and tags.
  </Card>

  <Card title="Knowledge Sync" icon="book" href="/knowledge/sources/front/connect">
    Train the AI on your Front Help Center articles.
  </Card>

  <Card title="Channels" icon="grid-2" href="/integrations/front/channels/email">
    Per-channel implementation details.
  </Card>

  <Card title="Troubleshooting" icon="wrench" href="/integrations/front/troubleshooting">
    Credentials failing, webhook silent, AI not replying.
  </Card>
</CardGroup>
