How to Extract Signed Contract Terms from Email Attachments Using Transient Knowledge

Build a Spojit workflow that catches a signed contract emailed to a Mailhook address, embeds the PDF into a Transient collection, asks Miraxa for the parties, key dates, and renewal terms using a Response Schema, then logs the result as a Monday.com item and posts a Slack summary.

What This Integration Does

Legal and operations teams receive signed contracts as email attachments and then re-key the same handful of facts (who signed, when it starts, when it renews, the notice window) into a tracker by hand. This workflow removes that step entirely. When a countersigned PDF lands in a dedicated mailbox, Spojit reads the document, pulls the structured terms with the intelligent layer across your automation, and writes them straight into a Monday.com board so your renewals tracker is always current.

A Mailhook trigger starts each run the moment a contract is emailed to a unique Spojit address. An Attachment node fetches the PDF bytes, a Knowledge node embeds those bytes into a Transient collection, and a second Knowledge node queries that collection with a Response Schema so the output is reliable JSON. The terms are written to Monday.com and announced in Slack. The Transient collection lives only for the run and is discarded on completion, so nothing accumulates between contracts. Each email is deduplicated per message, so the same contract emailed twice does not create two board items.

Prerequisites

  • A workflow in the Spojit designer with its Trigger set to Mailhook, and a generated Mailhook address you can forward contracts to.
  • A Monday.com connection added under Connections, with a board for contract renewals. Note the board ID and (optionally) a target group ID.
  • A Slack connection added under Connections, with access to the channel where you want summaries posted.
  • Contracts arriving as PDF attachments under 10 MB each (the per-attachment default limit) and 25 MB per run.
  • No persistent collection is required: this workflow uses a Transient collection, which needs no file name or embedding model setup.

Step 1: Catch the contract with a Mailhook trigger

Open the Trigger node and set Trigger Type to Mailhook. Optionally set an Address prefix (for example contracts), then click Generate email address and copy the address, which looks like contracts-1a2b3c4d5e6f7g8h@mailhook.spojit.com. Point your signing tool's completion notice or a mailbox forwarding rule at that address. To keep stray mail out, add a From allowlist (for example your e-signature provider's sending domain) and an optional Subject regex such as (?i)signed|executed|countersigned. Every matching email starts a run within seconds, and the email is exposed downstream as {{ input }}, including {{ input.subject }}, {{ input.from }}, {{ input.replyTo }}, and the {{ input.attachments }} references.

Step 2: Fetch the PDF bytes with an Attachment node

Add an Attachment node directly after the trigger. The designer only saves this node when the trigger is a Mailhook, so it pairs naturally here. Set Mode to Single to grab the first matching file as an object, set the Content type filter to application/pdf, and set a Filename pattern like *.pdf to ignore signature-image attachments some tools add. Turn on Fail if no attachment matches so a misaddressed email does not silently produce an empty board entry. The node outputs an object you can reference as the attachment result with these fields:

{
  "filename": "msa-acme-signed.pdf",
  "contentType": "application/pdf",
  "size": 184320,
  "content": "JVBERi0xLjcKJ..."   // base64 bytes
}

The base64 content value feeds straight into the next node.

Step 3: Embed the contract into a Transient collection

Add a Knowledge node in Embed mode. In the Collection dropdown, pick Transient. A Transient collection is auto-created for this run, shared across nodes in the same run, and cleaned up when the run finishes, so you do not set a file name or embedding model. Set Document Type to PDF, and set Document Input to the base64 content from the Attachment node, for example {{ attachment.content }}. Assign an Output Variable (for example embedResult) so you can see the chunk count and metadata in the execution log. This step turns the signed PDF into searchable chunks that only the current run can query.

Step 4: Query for parties, dates, and renewal terms with a Response Schema

Add a second Knowledge node in Query mode and set its Collection to Transient so it reads the document embedded in Step 3. In the Prompt, ask the intelligent layer across your automation for exactly the facts you track:

Extract the contract parties, the effective date, the term end date,
the renewal type (auto-renew or manual), the renewal notice period in
days, and the total contract value if stated. Use ISO dates
(YYYY-MM-DD). If a field is not present, return null.

Set Result Count high enough to cover a multi-page contract (for example 8), pick a Model for synthesis, and define a Response Schema so the output is structured JSON rather than prose:

{
  "type": "object",
  "properties": {
    "parties": { "type": "array", "items": { "type": "string" } },
    "effectiveDate": { "type": "string" },
    "termEndDate": { "type": "string" },
    "renewalType": { "type": "string" },
    "noticePeriodDays": { "type": "integer" },
    "contractValue": { "type": "string" }
  },
  "required": ["parties", "effectiveDate", "termEndDate", "renewalType"]
}

Assign an Output Variable such as terms. Downstream nodes then reference fields like {{ terms.effectiveDate }} and {{ terms.renewalType }} with confidence, because the schema forces the shape.

Step 5: Log the terms to a Monday.com board

Add a Connector node, choose your Monday.com connection in Direct mode, and select the create-item tool. Direct mode is right here because the action is a single deterministic write with no AI cost. Map the fields:

  • boardId to your renewals board ID.
  • name to a readable item title, for example {{ input.subject }} or the first party from {{ terms.parties }}.
  • groupId (optional) to the group that holds active contracts.
  • columnValues to a JSON object that maps your board columns to the extracted terms.

A typical columnValues payload (replace the column IDs with your board's own) looks like:

{
  "date_effective": { "date": "{{ terms.effectiveDate }}" },
  "date_renewal": { "date": "{{ terms.termEndDate }}" },
  "text_renewal_type": "{{ terms.renewalType }}",
  "numbers_notice_days": "{{ terms.noticePeriodDays }}",
  "text_value": "{{ terms.contractValue }}"
}

Use list-boards or get-board once during setup to read your exact column IDs, then paste them into the mapping above.

Step 6: Announce the new contract in Slack

Add a final Connector node, choose your Slack connection in Direct mode, and select send-message. Set the channel to your contracts channel and compose a text summary from the extracted terms so the team sees the headline facts without opening the board:

New signed contract logged.
Parties: {{ terms.parties }}
Effective: {{ terms.effectiveDate }}  Renews: {{ terms.termEndDate }}
Renewal: {{ terms.renewalType }} ({{ terms.noticePeriodDays }} days notice)
Source email: {{ input.subject }}

If you would rather email a confirmation back to whoever sent the contract, add a Send Email node and address it to {{ input.replyTo }}, since Mailhook runs are always asynchronous and do not reply to the sender automatically.

Tips

  • Keep Mode as Single when each email carries exactly one contract. If counterparties sometimes send several PDFs in one email, switch to Multiple and wrap Steps 3 and 4 in a Loop over {{ attachment.attachments }}.
  • Always use the same Transient collection across the embed and query nodes in a run: because both point at Transient, the query reads exactly what the embed just wrote, then both are discarded on completion.
  • Tighten the Subject regex and From allowlist on the trigger so internal CCs or reply-all threads do not start needless runs.
  • Store dates in ISO format in the Response Schema so Monday.com date columns accept them without reformatting.

Common Pitfalls

  • The designer refuses to save an Attachment node unless the trigger is a Mailhook. If you started from an Email trigger that polls Gmail or Outlook, reference attachment bytes through that trigger's own output instead.
  • Scanned contracts that are image-only PDFs may embed with little text. If extraction is thin, set the embed Document Type to an image type so OCR runs, or ask the counterparty for a text-based PDF.
  • Wrong Monday.com column IDs cause create-item to drop values silently. Confirm IDs with get-board before going live, and match each column's expected JSON shape (date columns want { "date": "..." }).
  • Attachments above the 10 MB per-attachment or 25 MB per-run limits will not be fetched. For large bundles, send the contract as its own email rather than batching scans together.

Testing

Before pointing live signing notices at the address, email one sample signed PDF to your Mailhook address from an allowlisted sender, then open the run in the execution history. Confirm the Attachment node returned a non-empty content, the embed node reported a sensible chunk count, and the query node's terms output matches the schema. Check that the Monday.com item appeared with the right column values and that the Slack message posted to the correct channel. Once a single contract flows end to end, forward a couple of older signed agreements to confirm the extraction holds across formats, then route your signing tool's completion notices to the address.

Learn More

Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.