feat(square): add Square integration with 34 commerce operations#5053
Conversation
Add a Square integration (API-key auth via personal access token) covering payments, refunds, customers, locations, orders, invoices, catalog, and inventory. Catalog image upload routes through an internal API endpoint using the shared UserFile handling pattern. Adds a dedicated square-errors extractor.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
@greptile |
PR SummaryMedium Risk Overview Most calls hit Square’s REST API directly from tool configs; catalog image upload is the exception—a new internal Docs, Reviewed by Cursor Bugbot for commit 6b161a7. Configure here. |
|
@cursor review |
There was a problem hiding this comment.
✅ 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 339ec6e. Configure here.
Greptile SummaryThis PR adds a comprehensive Square commerce integration with 34 operations across Payments, Refunds, Customers, Locations, Orders, Invoices, Catalog, and Inventory. The implementation follows established patterns in the codebase — a multi-operation block with per-field conditions and a shared
Confidence Score: 5/5Safe to merge — the integration is additive (no changes to existing paths) and follows established tool/block patterns throughout. All 34 tools correctly use apps/sim/tools/square/search_invoices.ts — the exposed interface is more limited than the underlying Square Search Invoices endpoint allows. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
Block["Square Block\n(operation dropdown)"] --> Coerce["tools.config.params\nJSON parse · number coerce · boolean coerce"]
Coerce --> ToolSel["tools.config.tool\nsquare_\${operation}"]
ToolSel --> PayTools["Payment Tools\ncreate / get / list / cancel / complete"]
ToolSel --> RefTools["Refund Tools\nrefund / get / list"]
ToolSel --> CustTools["Customer Tools\ncreate / get / list / search / update / delete"]
ToolSel --> LocTools["Location Tools\nlist / get"]
ToolSel --> OrdTools["Order Tools\ncreate / get / search / pay"]
ToolSel --> InvTools["Invoice Tools\ncreate / get / list / search / publish / cancel / delete"]
ToolSel --> CatTools["Catalog Tools\nupsert / get / list / search / delete"]
ToolSel --> ImgTool["Catalog Image\n(create_catalog_image)"]
ToolSel --> InvCounts["Inventory\nbatch_retrieve_counts"]
PayTools --> SquareAPI["Square REST API\nconnect.squareup.com\n+ Square-Version header"]
RefTools --> SquareAPI
CustTools --> SquareAPI
LocTools --> SquareAPI
OrdTools --> SquareAPI
InvTools --> SquareAPI
CatTools --> SquareAPI
InvCounts --> SquareAPI
ImgTool --> InternalRoute["/api/tools/square/catalog-image\nDownload file · Build multipart form"]
InternalRoute --> SquareCatImg["Square Catalog Images API\nPOST /v2/catalog/images"]
SquareAPI --> ErrExt["square-errors extractor\nerrors[0].detail + code"]
Reviews (11): Last reviewed commit: "fix(square): validate parsed JSON field ..." | Re-trigger Greptile |
Greptile SummaryThis PR adds a complete Square integration with 34 operations spanning Payments, Refunds, Customers, Locations, Orders, Invoices, Catalog, and Inventory. Authentication uses a personal access token (PAT) via
Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant UI as Block UI
participant Exec as Tool Executor (index.ts)
participant Proxy as /api/tools/square/catalog-image
participant Square as Square API
UI->>Exec: "run square_${operation}"
Exec->>Exec: check !response.ok → errorExtractor(SQUARE_ERRORS)
alt Direct Square tool (e.g. create_payment)
Exec->>Square: POST /v2/payments (Bearer token)
Square-->>Exec: "200 OK {payment}"
Exec->>Exec: transformResponse → return output
else Catalog image upload
Exec->>Proxy: POST /api/tools/square/catalog-image
Proxy->>Proxy: checkInternalAuth + assertToolFileAccess
Proxy->>Proxy: downloadFileFromStorage
Proxy->>Square: POST /v2/catalog/images (multipart)
Square-->>Proxy: "200 OK {image}"
Proxy-->>Exec: "200 {success:true, output:{object, metadata}}"
Exec->>Exec: transformResponse checks data.success
end
Exec-->>UI: tool output
Reviews (2): Last reviewed commit: "feat(square): add Square integration wit..." | Re-trigger Greptile |
- Fix catalog image upload: Square's multipart part for the binary is `file`, not `image_file` (per the live API cURL examples); this would have caused upload failures - Catalog image route: check response.ok before parsing, drop the unreachable legacy base64 path, derive MIME from the uploaded file - Block: split the search query field per operation so placeholders match each endpoint's schema; parse each JSON field individually so errors name the field - Round out coverage: complete_payment version_token; customer nickname/birthday; batch inventory states/updated_after/limit
|
@greptile recheck |
|
@cursor review |
There was a problem hiding this comment.
✅ 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 81d5107. Configure here.
|
@greptile |
- Read the catalog image file from the canonical `params.file` (the basic/advanced inputs are collapsed before the params function runs) instead of the raw uploadFile/fileRef ids, which no longer exist at that point — fixes the Canonical Param Validation test and a latent upload bug - Revert the per-operation query split: canonicalParamId is only valid for basic/advanced pairs under one condition. Use a single query field with a schema-neutral placeholder and a wand prompt that covers each search operation
|
@greptile |
|
@cursor review |
There was a problem hiding this comment.
✅ 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 4c7ea07. Configure here.
|
@greptile |
|
@greptile review |
|
@greptile |
|
@cursor review |
- SearchInvoices: Square's invoice filter accepts only one location, so take a single locationId (string) instead of an array and wrap it as query.filter.location_ids: [locationId] - Block: fail locally with a clear "<field> must be a valid number" error when amount/limit/version/orderVersion are non-numeric instead of forwarding NaN
|
@greptile |
|
@cursor review |
Coerce these from both the dropdown's string values and actual booleans (which can arrive via connected blocks or templated inputs), so true is not silently flipped to false.
|
@greptile |
|
@cursor review |
parseJsonField now enforces the expected shape so a valid-but-wrong-type value (e.g. a JSON string where an array is expected for locationIds/objectTypes/ paymentIds/catalogObjectIds/states, or a non-object for order/invoice/etc.) fails locally with a clear message instead of a confusing Square API error.
|
@greptile |
|
@cursor review |
There was a problem hiding this comment.
✅ 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 6b161a7. Configure here.
Summary
/api/tools/square/catalog-image) using the sharedUserFiledownload + multipart pattern (same as Box)square-errorsextractor (errors[].detail+ code) so Square API errors surface cleanlytools.config.params, and aSquareBlockMetawith 7 templates + 4 skillsOperations
Type of Change
Testing
Tested manually; typecheck clean,
bun run check:api-validation:strictpasses, docs regenerated.Checklist