{% set mauticBaseUrl = app.request ? app.request.schemeAndHttpHost : 'https://mautic.example.com' %}

<div class="row">
    <div class="col-md-12">
        <div class="panel panel-default">
            <div class="panel-heading"><strong>Authenticated API</strong></div>
            <div class="panel-body">
                <p class="mb-md">
                    Use your normal Mautic API authentication against the Deal Flow API. Every request still enforces Deal Flow permissions,
                    so a caller can only read or mutate records that their user or token is allowed to access.
                </p>
                <p class="mb-md">
                    Example requests below use <code>{{ mauticBaseUrl }}</code>. JSON endpoints expect <code>Content-Type: application/json</code>.
                    Attachment uploads use <code>multipart/form-data</code> with a single file field named <code>attachment</code>.
                </p>
                <p class="mb-0">
                    Deal dates use <code>YYYY-MM-DD</code> for <code>expected_close_date</code>. Task due dates and timestamps use ISO 8601
                    strings such as <code>2026-03-18T15:00:00Z</code>.
                </p>
            </div>
        </div>
    </div>
</div>

<div class="row">
    <div class="col-md-6">
        <div class="panel panel-default">
            <div class="panel-heading"><strong>Deal response object</strong></div>
            <div class="panel-body">
                <pre class="dealflow-docs-code mb-0"><code>{
  "id": 123,
  "title": "Acme Renewal",
  "status": "open",
  "stage": {
    "id": 5,
    "name": "Proposal",
    "type": "open"
  },
  "amount": "25000.0000",
  "currency": "USD",
  "confidence": 70,
  "company_id": 42,
  "company_name": "Acme Corp",
  "owner_id": 7,
  "owner_name": "Jane Seller",
  "external_ref": "crm-123",
  "expected_close_date": "2026-03-31",
  "description": "Renewal for enterprise plan",
  "contacts": [
    {
      "id": 99,
      "label": "Decision Maker",
      "name": "Pat Buyer",
      "email": "buyer@example.com",
      "createdAt": "2026-03-10T18:12:00+00:00"
    }
  ],
  "updated_at": "2026-03-11T14:30:00+00:00",
  "created_at": "2026-03-10T18:12:00+00:00"
}</code></pre>
            </div>
        </div>
    </div>
    <div class="col-md-6">
        <div class="panel panel-default">
            <div class="panel-heading"><strong>Other response envelopes</strong></div>
            <div class="panel-body">
                <p><strong>List response</strong></p>
                <pre class="dealflow-docs-code"><code>{
  "total": 1,
  "items": [
    { "...": "deal object shown at left" }
  ]
}</code></pre>

                <p><strong>Task update response</strong></p>
                <pre class="dealflow-docs-code"><code>{
  "task": {
    "id": 456,
    "status": "completed",
    "title": "Send pricing packet",
    "due_at": "2026-03-18T15:00:00+00:00",
    "owner_id": 7
  }
}</code></pre>

                <p><strong>Attachment upload response</strong></p>
                <pre class="dealflow-docs-code"><code>{
  "attachment": {
    "id": 22,
    "deal_id": 123,
    "original_filename": "proposal.pdf",
    "mime_type": "application/pdf",
    "size_bytes": 183442,
    "uploaded_by": 7,
    "created_at": "2026-03-11T14:32:00+00:00",
    "download_path": "/s/deal-flow/attachments/22/download"
  }
}</code></pre>

                <p><strong>Timeline response</strong></p>
                <pre class="dealflow-docs-code mb-0"><code>{
  "timeline": [
    {
      "type": "note",
      "timestamp": "2026-03-11T14:35:00+00:00",
      "label": "Note added",
      "body": "Discovery call completed.",
      "meta": {
        "source_type": "manual"
      }
    }
  ]
}</code></pre>
            </div>
        </div>
    </div>
</div>

<div class="row">
    <div class="col-md-12">
        <div class="panel panel-default">
            <div class="panel-heading"><strong>Standard errors</strong></div>
            <div class="panel-body">
                <p class="mb-md">
                    API errors return a single <code>error</code> string. The most common status codes are
                    <code>400</code> for invalid payloads, <code>403</code> for missing Deal Flow permissions,
                    and <code>404</code> when the requested deal, stage, or task does not exist.
                </p>
                <pre class="dealflow-docs-code mb-0"><code>{
  "error": "Forbidden"
}</code></pre>
            </div>
        </div>
    </div>
</div>

<div class="row">
    <div class="col-md-12">
        <div class="panel panel-default">
            <div class="panel-heading"><strong>Available endpoints</strong></div>
            <div class="table-responsive">
                <table class="table mb-0">
                    <thead>
                    <tr>
                        <th>Method</th>
                        <th>Path</th>
                        <th>Request</th>
                        <th>Returns</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                        <td><code>GET</code></td>
                        <td><code>/api/dealflow/deals</code></td>
                        <td>Query parameters: <code>search</code>, <code>status</code>, <code>owner_id</code>, <code>company_id</code></td>
                        <td><code>{ total, items: [deal] }</code></td>
                    </tr>
                    <tr>
                        <td><code>POST</code></td>
                        <td><code>/api/dealflow/deals</code></td>
                        <td>Deal payload, optionally with <code>contacts</code></td>
                        <td><code>deal</code> object</td>
                    </tr>
                    <tr>
                        <td><code>GET</code></td>
                        <td><code>/api/dealflow/deals/{id}</code></td>
                        <td>No body</td>
                        <td><code>deal</code> object</td>
                    </tr>
                    <tr>
                        <td><code>PATCH</code></td>
                        <td><code>/api/dealflow/deals/{id}</code></td>
                        <td>Partial deal payload</td>
                        <td><code>deal</code> object</td>
                    </tr>
                    <tr>
                        <td><code>POST</code></td>
                        <td><code>/api/dealflow/deals/{id}/stage</code></td>
                        <td><code>{ "stage_id": 123 }</code></td>
                        <td><code>deal</code> object</td>
                    </tr>
                    <tr>
                        <td><code>POST</code></td>
                        <td><code>/api/dealflow/deals/{id}/contacts</code></td>
                        <td><code>{ "contacts": [...] }</code></td>
                        <td><code>deal</code> object</td>
                    </tr>
                    <tr>
                        <td><code>POST</code></td>
                        <td><code>/api/dealflow/deals/{id}/notes</code></td>
                        <td><code>{ "body": "...", "source_type": "manual" }</code></td>
                        <td><code>deal</code> object</td>
                    </tr>
                    <tr>
                        <td><code>POST</code></td>
                        <td><code>/api/dealflow/deals/{id}/tasks</code></td>
                        <td><code>{ "title": "...", "due_at": "..." }</code></td>
                        <td><code>deal</code> object</td>
                    </tr>
                    <tr>
                        <td><code>PATCH</code></td>
                        <td><code>/api/dealflow/deals/{id}/tasks/{taskId}</code></td>
                        <td>Partial task payload</td>
                        <td><code>{ task: ... }</code></td>
                    </tr>
                    <tr>
                        <td><code>POST</code></td>
                        <td><code>/api/dealflow/deals/{id}/attachments</code></td>
                        <td><code>multipart/form-data</code> with <code>attachment</code> file</td>
                        <td><code>{ attachment: ... }</code></td>
                    </tr>
                    <tr>
                        <td><code>GET</code></td>
                        <td><code>/api/dealflow/deals/{id}/timeline</code></td>
                        <td>No body</td>
                        <td><code>{ timeline: [...] }</code></td>
                    </tr>
                    <tr>
                        <td><code>POST</code></td>
                        <td><code>/dealflow/webhooks/inbound/{sourceKey}</code></td>
                        <td>Signed JSON payload with deal fields, contacts, note, and task support</td>
                        <td><code>{ "deal": { "event": "deal.webhook_processed", ... } }</code></td>
                    </tr>
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</div>

<div class="row">
    <div class="col-md-12">
        <div class="panel panel-default">
            <div class="panel-heading"><strong><code>/api/dealflow/deals</code></strong></div>
            <div class="panel-body">
                <h4 class="mt-0"><code>GET /api/dealflow/deals</code></h4>
                <div class="table-responsive">
                    <table class="table table-striped dealflow-docs-schema">
                        <tbody>
                        <tr>
                            <th>Permissions</th>
                            <td>Requires Deal Flow view access.</td>
                        </tr>
                        <tr>
                            <th>Query parameters</th>
                            <td><code>search</code>, <code>status</code>, <code>owner_id</code>, <code>company_id</code></td>
                        </tr>
                        <tr>
                            <th>Request body</th>
                            <td>None.</td>
                        </tr>
                        <tr>
                            <th>Success response</th>
                            <td><code>200 OK</code> with the list envelope shown above.</td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <pre class="dealflow-docs-code"><code>curl -X GET "{{ mauticBaseUrl }}/api/dealflow/deals?status=open&amp;owner_id=7" \
  -H "Authorization: Bearer &lt;token&gt;" \
  -H "Accept: application/json"</code></pre>

                <h4><code>POST /api/dealflow/deals</code></h4>
                <div class="table-responsive">
                    <table class="table table-striped dealflow-docs-schema">
                        <tbody>
                        <tr>
                            <th>Permissions</th>
                            <td>Requires Deal Flow create access.</td>
                        </tr>
                        <tr>
                            <th>Request object</th>
                            <td>
                                <code>title</code> string; <code>company_id</code> int or null; <code>owner_id</code> int or null;
                                <code>stage_id</code> int or <code>stage_slug</code> string; <code>amount</code> decimal string or null;
                                <code>currency</code> 3-letter code; <code>confidence</code> int or null; <code>source</code> string or null;
                                <code>external_ref</code> string or null; <code>expected_close_date</code> <code>YYYY-MM-DD</code> or null;
                                <code>description</code> string or null; optional <code>contacts</code> array.
                            </td>
                        </tr>
                        <tr>
                            <th><code>contacts[]</code></th>
                            <td>Each item may include <code>id</code>, <code>contact_id</code>, or <code>email</code>, plus optional <code>label</code>.</td>
                        </tr>
                        <tr>
                            <th>Success response</th>
                            <td><code>201 Created</code> with the deal object shown above.</td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <pre class="dealflow-docs-code mb-0"><code>curl -X POST "{{ mauticBaseUrl }}/api/dealflow/deals" \
  -H "Authorization: Bearer &lt;token&gt;" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Acme Renewal",
    "company_id": 42,
    "owner_id": 7,
    "stage_slug": "proposal",
    "amount": "25000.00",
    "currency": "USD",
    "confidence": 70,
    "external_ref": "crm-123",
    "expected_close_date": "2026-03-31",
    "description": "Renewal for enterprise plan",
    "contacts": [
      {
        "email": "buyer@example.com",
        "label": "Decision Maker"
      }
    ]
  }'</code></pre>
            </div>
        </div>
    </div>
</div>

<div class="row">
    <div class="col-md-12">
        <div class="panel panel-default">
            <div class="panel-heading"><strong><code>/api/dealflow/deals/{id}</code></strong></div>
            <div class="panel-body">
                <h4 class="mt-0"><code>GET /api/dealflow/deals/{id}</code></h4>
                <div class="table-responsive">
                    <table class="table table-striped dealflow-docs-schema">
                        <tbody>
                        <tr>
                            <th>Path parameters</th>
                            <td><code>id</code> is the Deal Flow deal id.</td>
                        </tr>
                        <tr>
                            <th>Permissions</th>
                            <td>Requires view access to that specific deal.</td>
                        </tr>
                        <tr>
                            <th>Request body</th>
                            <td>None.</td>
                        </tr>
                        <tr>
                            <th>Success response</th>
                            <td><code>200 OK</code> with the deal object shown above.</td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <pre class="dealflow-docs-code"><code>curl -X GET "{{ mauticBaseUrl }}/api/dealflow/deals/123" \
  -H "Authorization: Bearer &lt;token&gt;" \
  -H "Accept: application/json"</code></pre>

                <h4><code>PATCH /api/dealflow/deals/{id}</code></h4>
                <div class="table-responsive">
                    <table class="table table-striped dealflow-docs-schema">
                        <tbody>
                        <tr>
                            <th>Permissions</th>
                            <td>Requires edit access to that deal.</td>
                        </tr>
                        <tr>
                            <th>Request object</th>
                            <td>
                                Any subset of the deal fields accepted by deal creation, except contact attachments are handled by
                                <code>POST /api/dealflow/deals/{id}/contacts</code>.
                            </td>
                        </tr>
                        <tr>
                            <th>Success response</th>
                            <td><code>200 OK</code> with the updated deal object.</td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <pre class="dealflow-docs-code mb-0"><code>curl -X PATCH "{{ mauticBaseUrl }}/api/dealflow/deals/123" \
  -H "Authorization: Bearer &lt;token&gt;" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Acme Renewal - Legal Review",
    "amount": "27500.00",
    "confidence": 80,
    "expected_close_date": "2026-04-07",
    "description": "Pricing approved and waiting on redlines."
  }'</code></pre>
            </div>
        </div>
    </div>
</div>

<div class="row">
    <div class="col-md-12">
        <div class="panel panel-default">
            <div class="panel-heading"><strong><code>/api/dealflow/deals/{id}/stage</code> and <code>/contacts</code></strong></div>
            <div class="panel-body">
                <h4 class="mt-0"><code>POST /api/dealflow/deals/{id}/stage</code></h4>
                <div class="table-responsive">
                    <table class="table table-striped dealflow-docs-schema">
                        <tbody>
                        <tr>
                            <th>Permissions</th>
                            <td>Requires edit access to that deal.</td>
                        </tr>
                        <tr>
                            <th>Request object</th>
                            <td><code>{ "stage_id": 5 }</code>. The stage must exist in the same pipeline as the deal.</td>
                        </tr>
                        <tr>
                            <th>Success response</th>
                            <td><code>200 OK</code> with the refreshed deal object.</td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <pre class="dealflow-docs-code"><code>curl -X POST "{{ mauticBaseUrl }}/api/dealflow/deals/123/stage" \
  -H "Authorization: Bearer &lt;token&gt;" \
  -H "Content-Type: application/json" \
  -d '{
    "stage_id": 5
  }'</code></pre>

                <h4><code>POST /api/dealflow/deals/{id}/contacts</code></h4>
                <div class="table-responsive">
                    <table class="table table-striped dealflow-docs-schema">
                        <tbody>
                        <tr>
                            <th>Permissions</th>
                            <td>Requires edit access to that deal.</td>
                        </tr>
                        <tr>
                            <th>Request object</th>
                            <td>
                                <code>{ "contacts": [...] }</code>. Each item may include <code>id</code>, <code>contact_id</code>, or
                                <code>email</code>, plus optional <code>label</code>.
                            </td>
                        </tr>
                        <tr>
                            <th>Success response</th>
                            <td><code>200 OK</code> with the refreshed deal object. Contact associations are reflected in the deal’s <code>contacts</code> array.</td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <pre class="dealflow-docs-code mb-0"><code>curl -X POST "{{ mauticBaseUrl }}/api/dealflow/deals/123/contacts" \
  -H "Authorization: Bearer &lt;token&gt;" \
  -H "Content-Type: application/json" \
  -d '{
    "contacts": [
      {
        "contact_id": 99,
        "label": "Decision Maker"
      },
      {
        "email": "champion@example.com",
        "label": "Internal Champion"
      }
    ]
  }'</code></pre>
            </div>
        </div>
    </div>
</div>

<div class="row">
    <div class="col-md-12">
        <div class="panel panel-default">
            <div class="panel-heading"><strong><code>POST /api/dealflow/deals/{id}/attachments/from-form</code></strong></div>
            <div class="panel-body">
                <p>Copy a file from a Mautic form submission into a deal's attachment library. Useful for wiring form-based file uploads (e.g. RFP uploads) directly to a deal without re-uploading.</p>
                <div class="table-responsive">
                    <table class="table table-striped dealflow-docs-schema">
                        <tbody>
                        <tr>
                            <th>Permissions</th>
                            <td>Requires edit access to that deal.</td>
                        </tr>
                        <tr>
                            <th>Request object</th>
                            <td>
                                <code>form_submission_id</code> (integer, required) — ID of the Mautic form submission.<br>
                                <code>field_alias</code> (string, optional) — alias of the file upload field; defaults to <code>deal_file</code>.
                            </td>
                        </tr>
                        <tr>
                            <th>Success response</th>
                            <td><code>201 Created</code> with the new attachment object.</td>
                        </tr>
                        <tr>
                            <th>Error codes</th>
                            <td>
                                <code>404</code> deal or submission not found &bull;
                                <code>400</code> field not found, no file in submission, or file missing on disk &bull;
                                <code>409</code> file already attached to this deal
                            </td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <pre class="dealflow-docs-code mb-0"><code>curl -X POST "{{ mauticBaseUrl }}/api/dealflow/deals/42/attachments/from-form" \
  -H "Authorization: Bearer &lt;token&gt;" \
  -H "Content-Type: application/json" \
  -d '{
    "form_submission_id": 123,
    "field_alias": "deal_file"
  }'</code></pre>
            </div>
        </div>
    </div>
</div>

<div class="row">
    <div class="col-md-12">
        <div class="panel panel-default">
            <div class="panel-heading"><strong><code>/api/dealflow/deals/{id}/notes</code> and <code>/tasks</code></strong></div>
            <div class="panel-body">
                <h4 class="mt-0"><code>POST /api/dealflow/deals/{id}/notes</code></h4>
                <div class="table-responsive">
                    <table class="table table-striped dealflow-docs-schema">
                        <tbody>
                        <tr>
                            <th>Permissions</th>
                            <td>Requires edit access to that deal.</td>
                        </tr>
                        <tr>
                            <th>Request object</th>
                            <td><code>body</code> string is required. Optional: <code>source_type</code> string and <code>source_ref</code> string or null.</td>
                        </tr>
                        <tr>
                            <th>Success response</th>
                            <td><code>201 Created</code> with the refreshed deal object. The note itself is not returned as a separate envelope.</td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <pre class="dealflow-docs-code"><code>curl -X POST "{{ mauticBaseUrl }}/api/dealflow/deals/123/notes" \
  -H "Authorization: Bearer &lt;token&gt;" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "Discovery call completed. Procurement review starts next week.",
    "source_type": "manual",
    "source_ref": "call-2026-03-11"
  }'</code></pre>

                <h4><code>POST /api/dealflow/deals/{id}/tasks</code></h4>
                <div class="table-responsive">
                    <table class="table table-striped dealflow-docs-schema">
                        <tbody>
                        <tr>
                            <th>Permissions</th>
                            <td>Requires edit access to that deal.</td>
                        </tr>
                        <tr>
                            <th>Request object</th>
                            <td>
                                <code>title</code> string is required. Optional: <code>description</code> string or null,
                                <code>owner_id</code> int or null, and <code>due_at</code> ISO 8601 datetime.
                            </td>
                        </tr>
                        <tr>
                            <th>Success response</th>
                            <td><code>201 Created</code> with the refreshed deal object. The created task id is not returned by this endpoint.</td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <pre class="dealflow-docs-code mb-0"><code>curl -X POST "{{ mauticBaseUrl }}/api/dealflow/deals/123/tasks" \
  -H "Authorization: Bearer &lt;token&gt;" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Send pricing packet",
    "description": "Attach revised enterprise pricing and order form.",
    "owner_id": 7,
    "due_at": "2026-03-18T15:00:00Z"
  }'</code></pre>
            </div>
        </div>
    </div>
</div>

<div class="row">
    <div class="col-md-12">
        <div class="panel panel-default">
            <div class="panel-heading"><strong><code>/api/dealflow/deals/{id}/tasks/{taskId}</code> and <code>/attachments</code></strong></div>
            <div class="panel-body">
                <h4 class="mt-0"><code>PATCH /api/dealflow/deals/{id}/tasks/{taskId}</code></h4>
                <div class="table-responsive">
                    <table class="table table-striped dealflow-docs-schema">
                        <tbody>
                        <tr>
                            <th>Permissions</th>
                            <td>Requires edit access to that deal.</td>
                        </tr>
                        <tr>
                            <th>Request object</th>
                            <td>
                                Any subset of <code>title</code>, <code>description</code>, <code>owner_id</code>, or <code>due_at</code>.
                                To mark the task complete, send <code>{ "status": "completed" }</code>.
                            </td>
                        </tr>
                        <tr>
                            <th>Success response</th>
                            <td><code>200 OK</code> with the task envelope shown above.</td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <pre class="dealflow-docs-code"><code>curl -X PATCH "{{ mauticBaseUrl }}/api/dealflow/deals/123/tasks/456" \
  -H "Authorization: Bearer &lt;token&gt;" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "completed"
  }'</code></pre>

                <h4><code>POST /api/dealflow/deals/{id}/attachments</code></h4>
                <div class="table-responsive">
                    <table class="table table-striped dealflow-docs-schema">
                        <tbody>
                        <tr>
                            <th>Permissions</th>
                            <td>Requires edit access to that deal and Deal Flow attachment upload permission.</td>
                        </tr>
                        <tr>
                            <th>Request object</th>
                            <td><code>multipart/form-data</code> with a single file part named <code>attachment</code>.</td>
                        </tr>
                        <tr>
                            <th>File constraints</th>
                            <td>Current defaults allow PDF, Office documents, JPG, and PNG up to 50 MB.</td>
                        </tr>
                        <tr>
                            <th>Success response</th>
                            <td><code>201 Created</code> with the attachment envelope shown above.</td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <pre class="dealflow-docs-code mb-0"><code>curl -X POST "{{ mauticBaseUrl }}/api/dealflow/deals/123/attachments" \
  -H "Authorization: Bearer &lt;token&gt;" \
  -H "Accept: application/json" \
  -F "attachment=@/absolute/path/to/proposal.pdf"</code></pre>
            </div>
        </div>
    </div>
</div>

<div class="row">
    <div class="col-md-12">
        <div class="panel panel-default">
            <div class="panel-heading"><strong><code>/api/dealflow/deals/{id}/timeline</code></strong></div>
            <div class="panel-body">
                <div class="table-responsive">
                    <table class="table table-striped dealflow-docs-schema">
                        <tbody>
                        <tr>
                            <th>Permissions</th>
                            <td>Requires view access to that deal.</td>
                        </tr>
                        <tr>
                            <th>Request body</th>
                            <td>None.</td>
                        </tr>
                        <tr>
                            <th>Success response</th>
                            <td><code>200 OK</code> with <code>{ "timeline": [...] }</code>. Each item contains <code>type</code>, <code>timestamp</code>, <code>label</code>, <code>body</code>, and <code>meta</code>.</td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <pre class="dealflow-docs-code mb-0"><code>curl -X GET "{{ mauticBaseUrl }}/api/dealflow/deals/123/timeline" \
  -H "Authorization: Bearer &lt;token&gt;" \
  -H "Accept: application/json"</code></pre>
            </div>
        </div>
    </div>
</div>
