Skip to content

fix(loops): align integration with live API docs, add suppression + get-template tools#5358

Merged
waleedlatif1 merged 4 commits into
stagingfrom
worktree-loops-validate-integration
Jul 2, 2026
Merged

fix(loops): align integration with live API docs, add suppression + get-template tools#5358
waleedlatif1 merged 4 commits into
stagingfrom
worktree-loops-validate-integration

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Fixed loops_list_transactional_emails endpoint URL — was hitting /api/v1/transactional (the send endpoint), corrected to the documented /api/v1/transactional-emails list endpoint
  • Fixed response field mapping to match the actual API schema (createdAt/updatedAt) — the previous lastUpdated field never existed in Loops' API and was always undefined
  • Added 3 new tools backed by documented-but-previously-unsupported endpoints: loops_check_contact_suppression, loops_remove_contact_suppression, loops_get_transactional_email
  • Wired new tools into the block's operation dropdown, tools.access, tools.config, and outputs
  • Alphabetized Loops entries in tools/registry.ts

Type of Change

  • Bug fix
  • New feature (additive tool coverage)

Testing

Validated every tool and the block against Loops' live OpenAPI spec (app.loops.so/openapi.yaml) via independent verification passes. Typecheck and lint clean.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

…et-template tools

- fix list_transactional_emails endpoint URL (was /transactional, now /transactional-emails)
- fix response fields to match actual API schema (createdAt/updatedAt, not the never-existent lastUpdated)
- add loops_check_contact_suppression, loops_remove_contact_suppression, loops_get_transactional_email tools
- wire new tools into block operations, outputs, and registries
- alphabetize tools/registry.ts loops entries
@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 2, 2026 3:34pm

Request Review

@cursor

cursor Bot commented Jul 2, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
The list endpoint fix changes real API behavior for existing workflows (likely fixing broken lists); remove suppression affects deliverability/compliance and is quota-limited.

Overview
Aligns the Loops integration with the live API and expands workflow coverage.

List transactional emails now calls /api/v1/transactional-emails instead of the send path /api/v1/transactional, and maps createdAt / updatedAt from the response. lastUpdated is kept as a deprecated alias of updatedAt so existing workflows still get a timestamp.

Three new block operations and tools: Check Contact Suppression and Remove Contact Suppression (email or user ID, quota fields on responses), and Get Transactional Email by template ID. The Loops block dropdown, param mapping, outputs, registry, and a manage-suppression-compliance skill template are wired for these.

Reviewed by Cursor Bugbot for commit bf5c0d5. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a broken endpoint URL in loops_list_transactional_emails (was hitting the send endpoint /api/v1/transactional instead of the list endpoint /api/v1/transactional-emails), corrects the response field mapping from lastUpdated to createdAt/updatedAt, and adds three new tools (loops_check_contact_suppression, loops_remove_contact_suppression, loops_get_transactional_email) backed by documented Loops API endpoints.

  • Bug fix: list_transactional_emails URL corrected and response fields aligned to actual Loops API schema; lastUpdated kept as a deprecated backwards-compatible alias of updatedAt.
  • New tools: Suppression check/remove (GET/DELETE /api/v1/contacts/suppression) and single-template fetch (GET /api/v1/transactional-emails/:id) — all three fully wired into the block dropdown, tools.access, tools.config, and block-level outputs.
  • Housekeeping: Loops entries in tools/registry.ts and tools/loops/index.ts are alphabetized; new types are added to types.ts and LoopsResponse union.

Confidence Score: 5/5

Safe to merge — all changes are additive tool registrations and a targeted bug fix to an incorrect URL, with no risk to existing operations.

The URL fix is precise and clearly documented. The three new tools follow the same patterns as every existing Loops tool: correct HTTP method, validated identifier requirement (at least one of email/userId enforced at the URL-builder level), well-typed responses, and full wiring into the block dropdown, access list, config switch, and block-level outputs. Types and registry entries are consistent. No existing functionality is altered beyond the transactional-emails list endpoint fix.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/blocks/blocks/loops.ts Adds three new operations to the dropdown, extends contactEmail/userId visibility conditions, makes transactionalId required for get_transactional_email, and wires all new outputs into the block-level outputs section.
apps/sim/tools/loops/check_contact_suppression.ts New tool for GET /api/v1/contacts/suppression; validates that at least one of email or userId is provided, maps response fields correctly, and marks optional outputs appropriately.
apps/sim/tools/loops/remove_contact_suppression.ts New tool for DELETE /api/v1/contacts/suppression; validates required identifier, surfaces quota info in both success and error responses.
apps/sim/tools/loops/get_transactional_email.ts New tool for GET /api/v1/transactional-emails/:id; encodes the ID, detects absence of id field as an error condition, and returns all documented fields.
apps/sim/tools/loops/list_transactional_emails.ts Fixes the endpoint URL to /api/v1/transactional-emails and maps createdAt/updatedAt correctly; lastUpdated kept as a deprecated alias with a clear comment.
apps/sim/tools/loops/types.ts Adds three new param and response interfaces; extends LoopsListTransactionalEmailsResponse with createdAt/updatedAt; updates the LoopsResponse union type.
apps/sim/tools/registry.ts Imports and registers the three new tools in alphabetical order alongside existing Loops tools.
apps/sim/tools/loops/index.ts Adds alphabetically ordered re-exports for the three new tool modules.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant UI as Loops Block UI
    participant Block as loops.ts (block config)
    participant Registry as tools/registry.ts
    participant Tool as Tool Handler
    participant API as Loops API

    UI->>Block: Select check_contact_suppression
    Block->>Block: "transformParams → {email, userId}"
    Block->>Registry: Resolve loops_check_contact_suppression
    Registry->>Tool: loopsCheckContactSuppressionTool
    Tool->>API: "GET /api/v1/contacts/suppression?email=..."
    API-->>Tool: "{isSuppressed, contact, removalQuota}"
    Tool-->>Block: "{success, isSuppressed, contactId, removalQuotaLimit, removalQuotaRemaining}"

    UI->>Block: Select remove_contact_suppression
    Block->>Registry: Resolve loops_remove_contact_suppression
    Registry->>Tool: loopsRemoveContactSuppressionTool
    Tool->>API: "DELETE /api/v1/contacts/suppression?email=..."
    API-->>Tool: "{success, message, removalQuota}"
    Tool-->>Block: "{success, message, removalQuotaLimit, removalQuotaRemaining}"

    UI->>Block: Select get_transactional_email
    Block->>Registry: Resolve loops_get_transactional_email
    Registry->>Tool: loopsGetTransactionalEmailTool
    Tool->>API: GET /api/v1/transactional-emails/:id
    API-->>Tool: "{id, name, draftEmailMessageId, publishedEmailMessageId, ...}"
    Tool-->>Block: Full template object

    UI->>Block: Select list_transactional_emails
    Block->>Registry: Resolve loops_list_transactional_emails
    Registry->>Tool: loopsListTransactionalEmailsTool
    Tool->>API: GET /api/v1/transactional-emails
    API-->>Tool: "{data: [{id, name, createdAt, updatedAt, dataVariables}], pagination}"
    Tool-->>Block: "{transactionalEmails, pagination}"
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant UI as Loops Block UI
    participant Block as loops.ts (block config)
    participant Registry as tools/registry.ts
    participant Tool as Tool Handler
    participant API as Loops API

    UI->>Block: Select check_contact_suppression
    Block->>Block: "transformParams → {email, userId}"
    Block->>Registry: Resolve loops_check_contact_suppression
    Registry->>Tool: loopsCheckContactSuppressionTool
    Tool->>API: "GET /api/v1/contacts/suppression?email=..."
    API-->>Tool: "{isSuppressed, contact, removalQuota}"
    Tool-->>Block: "{success, isSuppressed, contactId, removalQuotaLimit, removalQuotaRemaining}"

    UI->>Block: Select remove_contact_suppression
    Block->>Registry: Resolve loops_remove_contact_suppression
    Registry->>Tool: loopsRemoveContactSuppressionTool
    Tool->>API: "DELETE /api/v1/contacts/suppression?email=..."
    API-->>Tool: "{success, message, removalQuota}"
    Tool-->>Block: "{success, message, removalQuotaLimit, removalQuotaRemaining}"

    UI->>Block: Select get_transactional_email
    Block->>Registry: Resolve loops_get_transactional_email
    Registry->>Tool: loopsGetTransactionalEmailTool
    Tool->>API: GET /api/v1/transactional-emails/:id
    API-->>Tool: "{id, name, draftEmailMessageId, publishedEmailMessageId, ...}"
    Tool-->>Block: Full template object

    UI->>Block: Select list_transactional_emails
    Block->>Registry: Resolve loops_list_transactional_emails
    Registry->>Tool: loopsListTransactionalEmailsTool
    Tool->>API: GET /api/v1/transactional-emails
    API-->>Tool: "{data: [{id, name, createdAt, updatedAt, dataVariables}], pagination}"
    Tool-->>Block: "{transactionalEmails, pagination}"
Loading

Reviews (4): Last reviewed commit: "fix(loops): update id output description..." | Re-trigger Greptile

Comment thread apps/sim/blocks/blocks/loops.ts
- add missing contactId block output for check_contact_suppression (Greptile P1)
- fix list_transactional_emails description to mention createdAt (Greptile P2)
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 7c49c26. Configure here.

…nsactional_emails

Final validation pass found that /api/v1/transactional (the endpoint this tool
used before this PR) is a real, functional, deprecated Loops endpoint whose
schema genuinely returns lastUpdated - it was not a broken/invented field.
Migrating to /api/v1/transactional-emails is still correct (current endpoint,
better error semantics), but dropping lastUpdated would break any existing
workflow reading it from this block's output. Keep it as a deprecated alias
of updatedAt alongside the new createdAt/updatedAt fields.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 57014a3. Configure here.

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit bf5c0d5. Configure here.

@waleedlatif1 waleedlatif1 merged commit dabb856 into staging Jul 2, 2026
29 of 30 checks passed
@waleedlatif1 waleedlatif1 deleted the worktree-loops-validate-integration branch July 2, 2026 16:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant