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

# Correggere automaticamente i ticket tramite webhook

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="Correzione automatica dei ticket tramite webhook" description="Collega i sistemi di ticketing on-prem o non supportati a Devin con un bridge da webhook a sessione." prompt="Aiutami a configurare una pipeline webhook-to-Devin per il mio sistema di ticketing. Segui la guida su https://docs.devin.ai/use-cases/gallery/api-webhook-custom-ticketing e accompagnami in ogni fase: creazione di un utente di servizio, sviluppo del gestore webhook e configurazione del mio sistema di ticketing per inviargli gli eventi." category="Automazioni" features="API, Playbooks" />

<div className="uc-detail-wrapper">
  <Tip>Non vuoi configurarlo manualmente? Incolla un collegamento a questa pagina in una sessione di Devin e chiedigli di impostare tutto per te.</Tip>

  <Steps>
    <Step title="Crea un utente di servizio">
      Devin utilizza i [service user tokens](/it/api-reference/v3/overview) per autenticare le chiamate API. Questo è l'approccio consigliato per l'automazione in ambiente di produzione.

      1. Vai su [app.devin.ai](https://app.devin.ai/?utm_source=docs\&utm_medium=use-case-gallery) > **Settings** > **Service Users** e crea un nuovo service user con l'autorizzazione `ManageOrgSessions`
      2. Copia il token API mostrato dopo la creazione e conservalo in modo sicuro — viene visualizzato solo una volta e lo utilizzerai come `DEVIN_API_KEY` nell'handler del tuo webhook

      Per trovare l'ID della tua organizzazione, esegui `GET https://api.devin.ai/v3/enterprise/organizations` con il tuo token — l'URL mostra solo lo slug dell'organizzazione, non l'ID.

      Esegui un rapido test con curl:

      ```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."}'
      ```

      Riceverai un `session_id` e un `url`. Elimina la sessione di test nella web app di Devin e continua.
    </Step>

    <Step title="Implementa il gestore del webhook">
      Questo pattern è ideale per **sistemi di ticketing on-prem** (come Jira self-hosted, Redmine o Bugzilla) o **strumenti di ticketing che non hanno un'integrazione nativa con Devin** (a differenza di [Linear](/it/integrations/linear) e [Jira Cloud](/it/integrations/jira), che offrono supporto integrato). Se il tuo sistema di ticketing supporta i webhook, puoi collegarlo a Devin con un piccolo servizio.

      Includi nel prompt un link alla documentazione dell'API del tuo sistema di ticketing, così Devin può capire come inviare commenti ai ticket. Passa il token dell'API di ticketing come [session secret](/it/api-reference/common-flows) in modo che Devin possa autenticarsi direttamente.

      Chiedi a Devin di creare lo scheletro del servizio:

      <PromptBlock>
        ```txt Webhook handler for custom ticketing theme={null}
        Crea un servizio Express.js che:
        1. Accetta POST /webhooks/tickets con un body JSON contenente id, title,
           description e labels
        2. Verifica la firma del webhook usando HMAC-SHA256
        3. Ignora i ticket che non hanno l'etichetta "devin-autofix" o "devin-feature"
        4. Chiama POST https://api.devin.ai/v3/organizations/{org_id}/sessions
           con un prompt costruito dai campi del ticket, un playbook_id basato
           sulla label e il token dell'API di ticketing come session secret

        Leggi DEVIN_API_KEY, DEVIN_ORG_ID, TICKET_API_TOKEN e WEBHOOK_SECRET
        dalle variabili d'ambiente.
        ```
      </PromptBlock>

      Ecco come si presenta l'handler principale:

      ```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 mappa `PLAYBOOKS` associa le etichette dei ticket ai [playbook](/it/product-guides/creating-playbooks) che crei in **Settings > Playbooks**. Un playbook per la correzione di bug potrebbe dire *"Aggiungi sempre un test di regressione"*; un playbook per le feature potrebbe dire *"Crea una PR in bozza e richiedi una revisione."*

      Il prompt include un link alla documentazione API del tuo sistema di ticketing, così Devin sa come pubblicare i commenti in risposta. Il `TICKET_API_TOKEN` viene passato come [session secret](/it/api-reference/common-flows) — viene iniettato come variabile d'ambiente solo per quella sessione e non viene mai archiviato. Sostituisci l'URL della documentazione API con la documentazione effettiva del tuo sistema di ticketing.

      Distribuisci l'handler in qualsiasi ambiente che possa ricevere richieste HTTPS POST — una funzione cloud (AWS Lambda, Google Cloud Functions), un container o un VPS. Registra il suo URL come webhook nelle impostazioni di notifica o integrazione del tuo sistema di ticketing e filtra per gli eventi **ticket created**.

      Crea un ticket di test con l'etichetta `devin-autofix` per verificare l'intero ciclo: ticket creato → webhook attivato → sessione Devin avviata → PR aperta → Devin pubblica un commento sul ticket.
    </Step>
  </Steps>
</div>
