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

# Correction automatique de tickets via webhooks

export const UseCaseHero = ({title, description, prompt, category, features, devinUrl, agent, intent, playbookId, type}) => {
  const encodedPrompt = encodeURIComponent(prompt || '');
  const tag = 'docs-use-case-gallery';
  const utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=hero-cta';
  const agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  const devinHref = type === 'schedule' ? 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + (prompt ? '&prompt=' + encodedPrompt : '') : type === 'review' ? 'https://app.devin.ai/review?' + utm : agent === 'ada' ? 'https://app.devin.ai/search?' + utm + '&noSubmit=true' + (prompt ? '&prompt=' + encodedPrompt : '') : devinUrl ? devinUrl.includes('?') ? devinUrl + '&' + utm + agentParams : devinUrl + '?' + utm + agentParams : prompt ? 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encodedPrompt : 'https://app.devin.ai/?' + utm + agentParams;
  const buttonLabel = type === 'schedule' ? 'Schedule in Devin ↗' : type === 'review' ? 'Set Up Devin Review ↗' : agent === 'advanced' ? 'Try in Devin ↗' : agent === 'dana' ? 'Try in Dana ↗' : agent === 'ada' ? 'Try in Ask Devin ↗' : 'Try in Devin ↗';
  const featureList = features ? features.split(',').map(f => f.trim()) : [];
  return <div className="uc-hero">
      <div className="uc-hero-inner">
        <div className="uc-hero-left">
          <h1 className="uc-hero-title">{title}</h1>
          <p className="uc-hero-desc">{description}</p>
          <div>
            <a href={devinHref} target="_blank" rel="noopener noreferrer" className="try-in-devin-btn">
              {buttonLabel}
            </a>
          </div>
        </div>
        <div className="uc-hero-meta">
          <div className="uc-meta-item">
            <span className="uc-meta-label">Author</span>
            <span className="uc-meta-value">Cognition</span>
          </div>
          <div className="uc-meta-item">
            <span className="uc-meta-label">Category</span>
            <span className="uc-meta-value">{category}</span>
          </div>
          {featureList.length > 0 && <div className="uc-meta-item">
              <span className="uc-meta-label">Features</span>
              <span className="uc-meta-value">{featureList.join(', ')}</span>
            </div>}
        </div>
      </div>
    </div>;
};

export const PromptBlock = ({children, type, agent, intent, playbookId}) => {
  var utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=prompt-block';
  var tag = 'docs-use-case-gallery';
  var agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  var label = type === 'schedule' ? 'Schedule in Devin' : type === 'playbook' ? 'Create Playbook' : type === 'knowledge' ? 'Add to Knowledge' : agent === 'advanced' ? 'Try in Devin' : agent === 'dana' ? 'Try in Dana' : agent === 'ada' ? 'Try in Ask Devin' : 'Try in Devin';
  var buildUrl = function (text) {
    var encoded = encodeURIComponent(text);
    if (type === 'schedule') return 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + '&prompt=' + encoded;
    if (type === 'playbook') return 'https://app.devin.ai/settings/playbooks/create?' + utm + '&body=' + encoded;
    if (type === 'knowledge') return 'https://app.devin.ai/knowledge?' + utm + '&body=' + encoded;
    if (agent === 'ada') return 'https://app.devin.ai/search?' + utm + '&noSubmit=true&prompt=' + encoded;
    return 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encoded;
  };
  const ref = React.useRef(null);
  const [href, setHref] = React.useState('#');
  React.useEffect(() => {
    if (!ref.current) return;
    var codeEl = ref.current.querySelector('pre code');
    if (codeEl) {
      var text = codeEl.textContent.trim();
      if (text) setHref(buildUrl(text));
    }
    var header = ref.current.querySelector('[data-component-part="code-block-header"]');
    if (header && !header.querySelector('.prompt-block-devin-link')) {
      var link = document.createElement('a');
      link.href = href;
      link.target = '_blank';
      link.rel = 'noopener noreferrer';
      link.className = 'prompt-block-devin-link';
      link.style.cssText = 'display:inline-flex;align-items:center;gap:6px;text-decoration:none;color:#fff;font-size:11px;font-weight:500;padding:4px 10px;border-radius:6px;white-space:nowrap;background:#317CFF;transition:background 0.2s;margin-left:8px;';
      link.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg> ' + label;
      link.onmouseenter = function () {
        link.style.background = '#2968D9';
      };
      link.onmouseleave = function () {
        link.style.background = '#317CFF';
      };
      header.appendChild(link);
    }
    var existingLink = ref.current.querySelector('.prompt-block-devin-link');
    if (existingLink && href !== '#') existingLink.href = href;
  });
  return <div className="prompt-block" ref={ref}>{children}</div>;
};

<UseCaseHero title="Correction automatique des tickets via webhooks" description="Connectez des systèmes de ticketing sur site ou non pris en charge à Devin grâce à un pont webhook-vers-session." prompt="Aidez-moi à configurer un pipeline de webhook vers Devin pour mon système de ticketing. Suivez le guide sur https://docs.devin.ai/use-cases/gallery/api-webhook-custom-ticketing et accompagnez-moi à chaque étape : création d’un utilisateur de service, développement du gestionnaire de webhook et configuration de mon système de ticketing pour lui envoyer des événements." category="Automatisations" features="API, Playbooks" />

<div className="uc-detail-wrapper">
  <Tip>Vous ne souhaitez pas effectuer cette configuration manuellement ? Collez un lien vers cette page dans une session Devin et demandez-lui de tout configurer pour vous.</Tip>

  <Steps>
    <Step title="Créer un utilisateur de service">
      Devin utilise des [service user tokens](/fr/api-reference/v3/overview) pour authentifier les appels à l’API. C’est l’approche recommandée pour l’automatisation en production.

      1. Accédez à [app.devin.ai](https://app.devin.ai/?utm_source=docs\&utm_medium=use-case-gallery) > **Settings** > **Service Users** et créez un nouvel utilisateur de service avec l’autorisation `ManageOrgSessions`
      2. Copiez le jeton d’API affiché après la création et stockez-le en lieu sûr — il n’est affiché qu’une seule fois et vous l’utiliserez comme `DEVIN_API_KEY` dans votre gestionnaire de webhook

      Pour trouver l’ID de votre organisation, effectuez un appel `GET https://api.devin.ai/v3/enterprise/organizations` avec votre jeton — l’URL n’affiche que le slug de l’organisation, pas l’ID.

      Testez-le avec une commande curl rapide :

      ```bash theme={null}
      curl -X POST https://api.devin.ai/v3/organizations/YOUR_ORG_ID/sessions \
        -H "Authorization: Bearer YOUR_API_TOKEN" \
        -H "Content-Type: application/json" \
        -d '{"prompt": "Say hello — this is a test session."}'
      ```

      Vous devriez recevoir un `session_id` et une `url`. Supprimez la session de test dans l'application Web Devin, puis passez à la suite.
    </Step>

    <Step title="Créer un gestionnaire de webhook">
      Ce schéma est idéal pour les **systèmes de ticketing on‑premise** (comme Jira auto‑hébergé, Redmine ou Bugzilla) ou les **outils de ticketing qui n’ont pas d’intégration native avec Devin** (contrairement à [Linear](/fr/integrations/linear) et [Jira Cloud](/fr/integrations/jira), qui disposent d’une prise en charge intégrée). Si votre système de ticketing prend en charge les webhooks, vous pouvez le relier à Devin avec un petit service.

      Incluez un lien vers la documentation de l’API de votre système de ticketing dans le prompt afin que Devin puisse déterminer comment publier des commentaires sur les tickets. Transmettez le jeton de l’API de ticketing en tant que [session secret](/fr/api-reference/common-flows) pour que Devin puisse s’authentifier directement.

      Demandez à Devin de créer l’ossature :

      <PromptBlock>
        ```txt Webhook handler for custom ticketing theme={null}
        Crée un service Express.js qui :
        1. Accepte POST /webhooks/tickets avec un corps JSON contenant id, title,
           description et labels
        2. Vérifie la signature du webhook avec HMAC-SHA256
        3. Ignore les tickets qui n’ont pas l’étiquette "devin-autofix" ou "devin-feature"
        4. Appelle POST https://api.devin.ai/v3/organizations/{org_id}/sessions
           avec un prompt construit à partir des champs du ticket, un playbook_id
           basé sur l’étiquette, et le jeton d’API du système de ticketing comme
           session secret

        Lis DEVIN_API_KEY, DEVIN_ORG_ID, TICKET_API_TOKEN et WEBHOOK_SECRET
        à partir des variables d’environnement.
        ```
      </PromptBlock>

      Voici à quoi ressemble le handler principal :

      ```javascript theme={null}
      const PLAYBOOKS = {
        'devin-autofix': 'playbook-a1b2c3d4e5f6',
        'devin-feature': 'playbook-f6e5d4c3b2a1',
      };

      app.post('/webhooks/tickets', async (req, res) => {
        if (!verifySignature(req)) return res.status(401).send('Bad signature');

        const { id, title, description, labels } = req.body;
        const label = labels.find(l => PLAYBOOKS[l]);
        if (!label) return res.status(200).send('No Devin label — skipped');

        const orgId = process.env.DEVIN_ORG_ID;
        const { session_id } = await fetch(
          `https://api.devin.ai/v3/organizations/${orgId}/sessions`, {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${process.env.DEVIN_API_KEY}`,
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            prompt: [
              `Ticket ${id}: ${title}`,
              description,
              `Reference ticket ${id} in your commit message.`,
              `When done, post a comment on ticket ${id} with a summary of your`,
              `changes and a link to the PR. Use the ticketing API at`,
              `https://your-ticketing-system.com/api/docs to post the comment.`,
              `Authenticate with the $TICKET_API_TOKEN environment variable.`,
            ].join('\n\n'),
            playbook_id: PLAYBOOKS[label],
            session_secrets: [
              { key: 'TICKET_API_TOKEN', value: process.env.TICKET_API_TOKEN },
            ],
          }),
        }).then(r => r.json());

        res.json({ session_id });
      });
      ```

      La map `PLAYBOOKS` fait correspondre les libellés de tickets aux [playbooks](/fr/product-guides/creating-playbooks) que vous créez dans **Settings > Playbooks**. Un playbook de correction de bug pourrait dire *« Toujours ajouter un test de régression »* ; un playbook de fonctionnalité pourrait dire *« Créer une PR brouillon et demander une revue. »*

      Le prompt inclut un lien vers la documentation de l’API de votre système de ticketing afin que Devin sache comment y publier des commentaires. Le `TICKET_API_TOKEN` est transmis comme un [secret de session](/fr/api-reference/common-flows) — il est injecté comme variable d’environnement pour cette session uniquement et n’est jamais stocké. Remplacez l’URL de la documentation de l’API par la documentation réelle de votre système de ticketing.

      Déployez le handler n’importe où qui peut recevoir des requêtes HTTPS POST — une fonction cloud (AWS Lambda, Google Cloud Functions), un conteneur ou un VPS. Enregistrez son URL comme webhook dans les paramètres de notification ou d’intégration de votre système de ticketing, et filtrez sur les événements **ticket created**.

      Créez un ticket de test avec le libellé `devin-autofix` pour vérifier la boucle complète : « ticket created » → webhook déclenché → session Devin démarrée → PR ouverte → Devin publie un commentaire sur le ticket.
    </Step>
  </Steps>
</div>
