> ## 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.

# Tickets automatisch über Webhooks beheben

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="Tickets automatisch per Webhooks lösen" description="Verbinde lokale oder nicht unterstützte Ticketingsysteme über eine Webhook-zu-Session-Bridge mit Devin." prompt="Hilf mir dabei, eine Webhook-zu-Devin-Pipeline für mein Ticketingsystem einzurichten. Folge der Anleitung unter https://docs.devin.ai/use-cases/gallery/api-webhook-custom-ticketing und führe mich durch jeden Schritt: das Anlegen eines Service-Benutzers, das Erstellen des Webhook-Handlers und das Konfigurieren meines Ticketingsystems, damit es Ereignisse an ihn sendet." category="Automatisierungen" features="API, Playbooks" />

<div className="uc-detail-wrapper">
  <Tip>Möchten Sie dies nicht manuell einrichten? Fügen Sie einen Link zu dieser Seite in eine Devin-Sitzung ein und bitten Sie Devin, alles für Sie einzurichten.</Tip>

  <Steps>
    <Step title="Service-Benutzer erstellen">
      Devin verwendet [Service-User-Tokens](/de/api-reference/v3/overview) zur Authentifizierung von API-Aufrufen. Dies ist der empfohlene Ansatz für Automatisierung in Produktionsumgebungen.

      1. Wechseln Sie zu [app.devin.ai](https://app.devin.ai/?utm_source=docs\&utm_medium=use-case-gallery) > **Settings** > **Service Users** und erstellen Sie einen neuen Service User mit der Berechtigung `ManageOrgSessions`.
      2. Kopieren Sie das nach der Erstellung angezeigte API-Token und bewahren Sie es sicher auf — es wird nur einmal angezeigt und Sie verwenden es als `DEVIN_API_KEY` in Ihrem Webhook-Handler.

      Um Ihre Organisations-ID zu finden, rufen Sie `GET https://api.devin.ai/v3/enterprise/organizations` mit Ihrem Token auf — die URL zeigt nur den Organisations-Slug, nicht die ID.

      Testen Sie es mit einem kurzen curl-Befehl:

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

      Sie sollten eine `session_id` und eine `url` erhalten. Löschen Sie die Testsitzung in der Devin-Web-App und fahren Sie fort.
    </Step>

    <Step title="Webhook-Handler erstellen">
      Dieses Muster ist ideal für **On-Premises-Ticketing-Systeme** (wie selbstgehostetes Jira, Redmine oder Bugzilla) oder **Ticketing-Tools, die keine native Devin-Integration haben** (im Gegensatz zu [Linear](/de/integrations/linear) und [Jira Cloud](/de/integrations/jira), die integrierte Unterstützung bieten). Wenn Ihr Ticketing-System Webhooks unterstützt, können Sie es mit einem kleinen Service mit Devin verbinden.

      Fügen Sie einen Link zur API-Dokumentation Ihres Ticketing-Systems in den Prompt ein, damit Devin herausfinden kann, wie Kommentare zurück in die Tickets gepostet werden. Übergeben Sie das Ticketing-API-Token als [Session-Secret](/de/api-reference/common-flows), damit Devin sich direkt authentifizieren kann.

      Bitten Sie Devin, das Grundgerüst zu erstellen:

      <PromptBlock>
        ```txt Webhook handler for custom ticketing theme={null}
        Erstellen Sie einen Express.js-Service, der:
        1. POST /webhooks/tickets mit einem JSON-Body akzeptiert, der id, title,
           description und labels enthält
        2. Die Webhook-Signatur mit HMAC-SHA256 verifiziert
        3. Tickets ohne das Label "devin-autofix" oder "devin-feature" überspringt
        4. POST https://api.devin.ai/v3/organizations/{org_id}/sessions aufruft
           mit einem Prompt, der aus den Ticketfeldern erstellt wird, einer
           playbook_id basierend auf dem Label und dem Ticketing-API-Token
           als Session-Secret

        Lesen Sie DEVIN_API_KEY, DEVIN_ORG_ID, TICKET_API_TOKEN und WEBHOOK_SECRET
        aus Umgebungsvariablen.
        ```
      </PromptBlock>

      So sieht der zentrale Handler aus:

      ```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 });
      });
      ```

      Die `PLAYBOOKS`-Map ordnet Ticket-Labels den [Playbooks](/de/product-guides/creating-playbooks) zu, die du in **Settings > Playbooks** erstellst. Ein Bugfix-Playbook könnte sagen: *„Immer einen Regressionstest hinzufügen“*; ein Feature-Playbook könnte sagen: *„Erstelle eine Entwurfs-PR und fordere ein Review an.“*

      Der Prompt enthält einen Link zu den API-Dokumenten deines Ticketing-Systems, damit Devin weiß, wie es Kommentare zurück in das System posten kann. Der `TICKET_API_TOKEN` wird als [session secret](/de/api-reference/common-flows) übergeben – er wird nur für diese Session als Umgebungsvariable bereitgestellt und niemals gespeichert. Ersetze die API-Dokumentations-URL durch die tatsächliche URL der Dokumentation deines Ticketing-Systems.

      Stelle den Handler überall dort bereit, wo HTTPS-POST-Requests empfangen werden können – etwa als Cloud Function (AWS Lambda, Google Cloud Functions), in einem Container oder auf einem VPS. Registriere seine URL als Webhook in den Benachrichtigungs- oder Integrationseinstellungen deines Ticketing-Systems und filtere nach **ticket created**-Events.

      Erstelle ein Testticket mit dem Label `devin-autofix`, um den vollständigen Ablauf zu verifizieren: Ticket erstellt → Webhook wird ausgelöst → Devin-Session startet → PR wird geöffnet → Devin postet einen Kommentar zu dem Ticket.
    </Step>
  </Steps>
</div>
