@celigo/api-specs 0.2.131 → 0.2.133

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/ai-agent.yml CHANGED
@@ -158,7 +158,7 @@ paths:
158
158
  aiAgent:
159
159
  provider: gemini
160
160
  litellm:
161
- model: gemini/gemini-2.5-flash
161
+ model: gemini-2.5-flash
162
162
  maxCompletionTokens: 2000
163
163
  _overrides:
164
164
  gemini:
@@ -839,7 +839,8 @@ components:
839
839
  AiAgentConfig:
840
840
  type: object
841
841
  description: |
842
- AI Agent configuration used by both AiAgentImport and GuardrailImport (ai_agent type).
842
+ AI agent configuration for an AiAgentImport. An `ai_agent` guardrail is configured by
843
+ the guardrail spec's `GuardrailAiAgentConfig` instead, which has no `tools` arrays.
843
844
 
844
845
  Configures which AI provider and model to use, along with instructions, parameter
845
846
  tuning, output format, and available tools. Providers come in two families with
@@ -1112,7 +1113,6 @@ components:
1112
1113
  - gpt-5-mini
1113
1114
  - gpt-5-nano
1114
1115
  - gpt-4.1-mini
1115
- - gpt-4o
1116
1116
  x-celigo-ui-override: Required by the AI agent configuration form. Encoded here to mirror the form so builders produce connectable configurations.
1117
1117
  x-celigo-ai-guidance:
1118
1118
  - |-
@@ -1192,7 +1192,9 @@ components:
1192
1192
  minimum: 100
1193
1193
  maximum: 128000
1194
1194
  default: 5000
1195
- description: Maximum number of tokens in the model's response (server default observed live on create)
1195
+ description: |-
1196
+ Caps the length of the model's response, in tokens. An agent created without it is
1197
+ saved with 5000; raise it for long outputs such as large extractions.
1196
1198
  serviceTier:
1197
1199
  type: string
1198
1200
  enum:
@@ -5787,7 +5789,8 @@ components:
5787
5789
  - filter
5788
5790
  description: |-
5789
5791
  Filter applied to incoming records before they are sent to the LLM. Records that match
5790
- continue through the agent; records that don't are silently dropped.
5792
+ continue through the agent; records that don't skip it, counted as ignored with no model
5793
+ call, and continue to the next step.
5791
5794
  allOf:
5792
5795
  - $ref: '#/components/schemas/Filter'
5793
5796
  responseTransform:
package/dist/export.yml CHANGED
@@ -6196,7 +6196,7 @@ components:
6196
6196
  (`http.paging.body` likewise from its paging fields). A body that is not parseable JSON at
6197
6197
  rest — Handlebars block helpers outside a string value — renders every field EMPTY in that
6198
6198
  form, so keep templated variables inside a JSON string value:
6199
- `"variables": "{\"after\": {{#if export.http.paging.token}}\"{{export.http.paging.token}}\"{{else}}null{{/if}}}"`.
6199
+ `"variables": "{\"after\": {{#if export.http.paging.token}}\"{{export.http.paging.token}}\"{{else}}null{{/if}} }"`.
6200
6200
  - |-
6201
6201
  The GraphQL form has no relative URI field: the connection `baseURI` is expected to be the
6202
6202
  GraphQL endpoint (a saved `relativeURI` still applies but is not shown). Create GraphQL
package/dist/import.yml CHANGED
@@ -549,6 +549,10 @@ paths:
549
549
  composed, not delivered — an FTP import against an unreachable host
550
550
  still returns `{name, fileLocation}`.
551
551
 
552
+ The import runs with its own `settings` only: hooks receive
553
+ `options.settings` with an `import` key but no `integration` or `flow`
554
+ key, and no `_flowId` or `_integrationId`.
555
+
552
556
  The import must be saved; to run an import definition that is not saved
553
557
  (or a modified copy of one), use the virtual import
554
558
  `POST /v1/connections/{_id}/import`, which takes the import document in
@@ -1303,7 +1307,7 @@ components:
1303
1307
  ## EXAMPLES:
1304
1308
  - `{ "UserId": "12345", "Name": "John Doe", "Age": 30, "Preferences": { "Language": "en", "Notifications": true } }`
1305
1309
  examples:
1306
- - '{"id": "{{record.id}}", "name": "{{record.name}}", "total": {{record.total}}}'
1310
+ - '{"id": "{{record.id}}", "name": "{{record.name}}", "total": {{record.total}} }'
1307
1311
  updateExpression:
1308
1312
  type: string
1309
1313
  x-celigo-ui-override: Required by the DynamoDB import form when method is updateItem (dynamodb.updateExpression required, visibleWhen method=updateItem).
@@ -1966,7 +1970,10 @@ components:
1966
1970
  the Import's mapping step runs first and shapes the source record,
1967
1971
  then this template renders against that mapped record.
1968
1972
  Reference the mapped record with the ``record`` root when wrapping it (e.g.
1969
- ``{"requestData": {{{jsonSerialize record}}}}``).
1973
+ ``{"requestData": {{{jsonSerialize record}}} }``).
1974
+ Keep a literal ``}`` apart from a closing ``}}`` or ``}}}`` (a space is enough): the save
1975
+ accepts ``{{{jsonSerialize record}}}}``, but every record then fails with
1976
+ ``handlebars_template_parse_error``.
1970
1977
  Avoid bare ``{{{jsonSerialize record}}}`` with no wrapper — leave the field undefined instead.
1971
1978
  Also avoid wrapping a single post-mapped scalar field in ``jsonSerialize`` (e.g.
1972
1979
  ``{{{jsonSerialize record.<scalar>}}}``) — that pattern is brittle.
@@ -2029,9 +2036,9 @@ components:
2029
2036
 
2030
2037
  Typical shapes:
2031
2038
  - Message-bus envelope:
2032
- ``{"MessageBody": {"class": "EntityUpdate", "payload": {{{jsonSerialize record}}}}}``
2039
+ ``{"MessageBody": {"class": "EntityUpdate", "payload": {{{jsonSerialize record}}} }}``
2033
2040
  - Metadata wrap:
2034
- ``{"batchNumber": "{{timestamp dateTimeFormat CST}}", "interfaceType": "...", "requestData": {{{jsonSerialize record}}}}``
2041
+ ``{"batchNumber": "{{timestamp dateTimeFormat CST}}", "interfaceType": "...", "requestData": {{{jsonSerialize record}}} }``
2035
2042
  - Named single-record array wrap (when destination wants ``[record]`` but each request sends one):
2036
2043
  ``{"products": [{{{jsonSerialize record}}}]}``
2037
2044
 
@@ -2072,7 +2079,7 @@ components:
2072
2079
  current ``{{#each data}}`` item.
2073
2080
 
2074
2081
  Example shape:
2075
- ``{"header": {"sellerId": "{{connection.http.unencrypted.sellerId}}"}, "messages": [{{#each data}}{"sku": "{{sku}}", "qty": {{quantity}}}{{/each}}]}``
2082
+ ``{"header": {"sellerId": "{{connection.http.unencrypted.sellerId}}"}, "messages": [{{#each data}}{"sku": "{{sku}}", "qty": {{quantity}} }{{/each}}]}``
2076
2083
  - |-
2077
2084
  ## Anti-pattern — DO NOT wrap a post-mapped scalar in jsonSerialize
2078
2085
 
@@ -2157,7 +2164,7 @@ components:
2157
2164
  mix the two shapes in one body.
2158
2165
  examples:
2159
2166
  - - '{"name": "{{record.name}}", "email": "{{record.email}}"}'
2160
- - - '{"requestData": {{{jsonSerialize record}}}}'
2167
+ - - '{"requestData": {{{jsonSerialize record}}} }'
2161
2168
  - - '{"values": [{{#each batch_of_records}}{{{jsonSerialize this.record}}}{{#unless @last}},{{/unless}}{{/each}}]}'
2162
2169
  x-celigo-agent:
2163
2170
  - handlebars
@@ -2647,9 +2654,7 @@ components:
2647
2654
 
2648
2655
  The referenced helper bundles the polling config plus a required status
2649
2656
  export (polled to check progress) and a result export (fetches the
2650
- final payload). An import configured with an async helper cannot carry
2651
- its own transform, output filter, or preSavePage hook — put that
2652
- processing in the result export instead.
2657
+ final payload).
2653
2658
  examples:
2654
2659
  - 60a2c4e6f321d800129a1a3c
2655
2660
  x-celigo-agent:
@@ -2733,7 +2738,7 @@ components:
2733
2738
 
2734
2739
  - **Static** — only ``map`` + optional ``default``. No HTTP
2735
2740
  request issued. Use for small controlled vocabularies.
2736
- - **Dynamic** — ``method`` + ``relativeURI`` (+ ``postBody``,
2741
+ - **Dynamic** — ``method`` + ``relativeURI`` (+ ``body``,
2737
2742
  ``headers``, ``extract``). Issues a live HTTP request per
2738
2743
  lookup. Adds one HTTP request per record at runtime — factor
2739
2744
  this into flow design for high-volume syncs.
@@ -2771,14 +2776,18 @@ components:
2771
2776
  inject values from the incoming record — e.g.
2772
2777
  ``/customers?email={{{email}}}`` or
2773
2778
  ``/accounts/{{{accountId}}}``.
2774
- postBody:
2779
+ body:
2775
2780
  type: string
2776
2781
  x-celigo-agent:
2777
2782
  - handlebars
2778
2783
  description: |
2779
- Request body template for POST / PUT / PATCH lookup methods.
2780
- Typically a JSON string with Handlebars placeholders —
2781
- ``{"email":"{{{email}}}"}``. Ignored for GET / DELETE.
2784
+ Request body template for POST / PUT / PATCH lookup methods, typically
2785
+ a JSON string with Handlebars placeholders (``{"email":"{{{email}}}"}``);
2786
+ ignored for GET / DELETE. The record's fields sit at the top level:
2787
+ ``{{email}}`` renders the record's value, while ``{{record.email}}``
2788
+ renders empty.
2789
+ x-celigo-ai-guidance:
2790
+ - 'Put the lookup''s request template here, not in ``postBody``: a ``postBody`` saves without an error but is not kept under ``http.lookups``, so the lookup goes out with no body and the run reports no error.'
2782
2791
  headers:
2783
2792
  type: array
2784
2793
  items:
@@ -4429,9 +4438,9 @@ components:
4429
4438
  line) to the rows that populate the
4430
4439
  subrecord. Typically `$` when the
4431
4440
  subrecord data is carried on the same
4432
- line item (the enclosing
4433
- `lists[].jsonPath` has already selected
4434
- the line). Defaults to `$`.
4441
+ line item (iteration over the sublist
4442
+ has already selected the line).
4443
+ Defaults to `$`.
4435
4444
  mapping:
4436
4445
  type: object
4437
4446
  description: |
@@ -5155,9 +5164,10 @@ components:
5155
5164
  SQL `SELECT` statement that resolves the lookup value.
5156
5165
  Typically returns a single row with a single column; use
5157
5166
  `extract` to pick the column when the query returns multiple.
5158
- Inject values from the incoming record with Handlebars — RDBMS
5159
- queries use triple braces and the `record.` prefix:
5160
- `SELECT id FROM users WHERE email = '{{{record.email}}}'`.
5167
+ Inject values from the incoming record with Handlebars and the
5168
+ `record.` prefix — double braces for strings, which the platform
5169
+ quotes and escapes, and triple braces for numbers:
5170
+ `SELECT id FROM users WHERE email = {{record.email}}`.
5161
5171
  extract:
5162
5172
  type: string
5163
5173
  description: |
@@ -5205,7 +5215,7 @@ components:
5205
5215
  description: |-
5206
5216
  SQL statements to execute; required when queryType is `["per_record"]`, `["per_page"]`, or `["first_page"]`, and typically contains a single statement.
5207
5217
  Each element is a complete SQL statement as a plain string — never a single bare string and never an array of objects (objects cause a Cast error).
5208
- Inject values from the incoming record with Handlebars using the `record.` prefix and triple braces, e.g. `'{{{record.name}}}'` for strings (single-quoted in the SQL) and `{{{record.quantity}}}` for numbers.
5218
+ Inject values from the incoming record with Handlebars using the `record.` prefix: double braces for strings and dates (`{{record.name}}`; the platform quotes and escapes the value) and triple braces for numbers (`{{{record.quantity}}}`).
5209
5219
  Rendering is strict: a reference the render model cannot resolve (a bare `{{name}}` without prefix, or `record.*` when the arriving record is a grouped array) fails the step with `cannot_evaluate_handlebars` — it does not render an empty value.
5210
5220
  `record` and `rows` are aliases chosen by the arriving data's shape: an object record binds `record` (`rows` undefined); a grouped array-record (e.g. upstream `groupByFields`) binds `rows` (`record` undefined) — address grouped rows as `{{rows.0.field}}` or iterate `{{#each rows}}`.
5211
5221
  Double braces (`{{record.field}}`) output the value wrapped in single quotes with embedded quotes doubled, while triple braces output it raw; block helpers such as `{{#each}}` and `{{#if}}` use double braces as normal.
@@ -5219,7 +5229,7 @@ components:
5219
5229
  - CORRECT: ["INSERT INTO users (name, email) VALUES ({{record.name}}, {{record.email}})"]
5220
5230
  - WRONG: "INSERT INTO users ..." (not an array)
5221
5231
  - WRONG: [{"query": "INSERT INTO users ..."}] (objects are invalid — causes Cast error)
5222
- - WRONG: ["INSERT INTO users (name) VALUES ('{{name}}')"] (missing record. prefix — rendering is strict, so the step fails with cannot_evaluate_handlebars)
5232
+ - WRONG: ["INSERT INTO users (name) VALUES ({{name}})"] (missing record. prefix — rendering is strict, so the step fails with cannot_evaluate_handlebars)
5223
5233
  - |-
5224
5234
  ## RDBMS HANDLEBARS SYNTAX
5225
5235
 
@@ -5253,7 +5263,7 @@ components:
5253
5263
  | Numeric column value (INT, DECIMAL, ...) | `{{{record.field}}}` |
5254
5264
  | Stored procedure raw arg (already typed) | `{{{record.field}}}` |
5255
5265
  | Identifier (table/column name) | `{{{record.field}}}` |
5256
- | JSON literal (`PARSE_JSON`/JSONB) | `{{{jsonSerialize record.subobject}}}` |
5266
+ | JSON literal (`PARSE_JSON`/JSONB) | `{{jsonSerialize record.subobject}}` (renders the JSON as a quoted string) |
5257
5267
 
5258
5268
  - **Block helpers** (`{{#each}}`, `{{#if}}`, `{{/each}}`,
5259
5269
  `{{#unless}}`) use double braces as normal — they emit no value.
@@ -5272,7 +5282,7 @@ components:
5272
5282
  - Per-page batch (different Handlebars context — see `queryType: per_page` below): `["{{#each batch_of_records}}UPDATE staging SET done=1 WHERE id={{{this.record.id}}};{{/each}}"]`
5273
5283
  examples:
5274
5284
  - - INSERT INTO orders (id, total) VALUES ({{{record.id}}}, {{{record.total}}})
5275
- - - '{{#each batch_of_records}}UPDATE customers SET name=''{{{record.name}}}'' WHERE id={{{record.id}}};{{/each}}'
5285
+ - - '{{#each batch_of_records}}UPDATE customers SET name={{record.name}} WHERE id={{{record.id}}};{{/each}}'
5276
5286
  queryType:
5277
5287
  type:
5278
5288
  - array
@@ -5301,7 +5311,7 @@ components:
5301
5311
  Prefer the highest-performance type the operation supports: bulk_load (Snowflake, Google BigQuery, Microsoft SQL Server on a cloud connection, Azure Synapse and Amazon Redshift — handles INSERT, upsert via `bulkLoad.primaryKeys`, and custom merge or ignore-existing logic via `bulkLoad.overrideMergeQuery`), then bulk_insert for pure INSERTs, then per_page, then per_record only when the logic cannot be expressed as a batch operation.
5302
5312
  For UPDATE, UPSERT, or ignore-existing logic on databases without bulk_load support, use per_page or per_record with `query` — bulk_insert has no duplicate-checking logic.
5303
5313
  Set a single value; do not combine types or use the legacy INSERT and UPDATE values.
5304
- per_page statements render against the whole batch (`batch_of_records`) rather than a single record — loop with `{{#each batch_of_records}}...{{{record.fieldName}}}...{{/each}}`.
5314
+ per_page statements render against the whole batch (`batch_of_records`) rather than a single record — loop with `{{#each batch_of_records}}...{{record.fieldName}}...{{/each}}`, with the same quoting as `query` (double braces for strings, triple for numbers).
5305
5315
 
5306
5316
  `bulk_load` — Stages the records as files and loads them with the database's native COPY / bulk mechanism for maximum throughput; supports INSERT, upsert via bulkLoad.primaryKeys, and custom merge or ignore-existing logic via bulkLoad.overrideMergeQuery; available on Snowflake, Google BigQuery, Microsoft SQL Server (cloud connections), Azure Synapse and Amazon Redshift (NetSuite Analytics Warehouse has it through the JDBC import). The import form calls it "Use optimized bulk load (recommended for larger imports)" and, beside it, calls bulk_insert "Use batch insert SQL query".
5307
5317
  `bulk_insert` — Batch INSERT via multi-row VALUES clause for efficient bulk data loading; has no upsert or ignore-existing logic and is available for all RDBMS types.
@@ -5348,7 +5358,7 @@ components:
5348
5358
  Prompt: "Import customers, ignore existing based on email"
5349
5359
  ```json
5350
5360
  "queryType": ["per_record"],
5351
- "query": ["INSERT INTO customers (name, email) VALUES ('{{{record.name}}}', '{{{record.email}}}')"]
5361
+ "query": ["INSERT INTO customers (name, email) VALUES ({{record.name}}, {{record.email}})"]
5352
5362
  ```
5353
5363
 
5354
5364
  ### Pure INSERT (no duplicate checking)
@@ -5362,7 +5372,7 @@ components:
5362
5372
  Prompt: "Update inventory counts"
5363
5373
  ```json
5364
5374
  "queryType": ["per_record"],
5365
- "query": ["UPDATE inventory SET qty = {{{record.qty}}} WHERE sku = '{{{record.sku}}}'"]
5375
+ "query": ["UPDATE inventory SET qty = {{{record.qty}}} WHERE sku = {{record.sku}}"]
5366
5376
  ```
5367
5377
 
5368
5378
  ### Run Once Per Page
@@ -5370,7 +5380,7 @@ components:
5370
5380
  ```json
5371
5381
  "queryType": ["per_page"]
5372
5382
  ```
5373
- **per_page uses a different Handlebars context than per_record.** The context is the entire batch (`batch_of_records`), not a single `record.` object. Loop through with `{{#each batch_of_records}}...{{{record.fieldName}}}...{{/each}}`.
5383
+ **per_page uses a different Handlebars context than per_record.** The context is the entire batch (`batch_of_records`), not a single `record.` object. Loop through with `{{#each batch_of_records}}...{{record.fieldName}}...{{/each}}`, quoting as in per_record: double braces for strings, triple braces for numbers.
5374
5384
 
5375
5385
  ### Run Once at Start
5376
5386
  Prompt: "Run this cleanup script before processing"
@@ -8330,8 +8340,8 @@ components:
8330
8340
  description: |-
8331
8341
  Configuration for a `ToolImport`, which executes a reusable Celigo Tool resource as the
8332
8342
  import action. The referenced tool defines its own input contract, processing pipeline, and
8333
- output; this object binds the tool to the import and optionally overrides the connections the
8334
- tool uses for this invocation.
8343
+ output; this object binds the tool to the import, along with the connections the tool's steps
8344
+ use for this invocation.
8335
8345
  x-celigo-ai-guidance:
8336
8346
  - |-
8337
8347
  A ToolImport is the **wrapper** that lets a flow / API / another Tool consume a
@@ -8382,7 +8392,8 @@ components:
8382
8392
  Per-import overrides applied to the referenced tool at execution time. Tools use a
8383
8393
  bring-your-own-keys connection model: the tool declares abstract connection slots, and the
8384
8394
  consumer binds concrete connections here so one tool definition can run against different
8385
- systems without being modified. Omit to run the tool with its default connections.
8395
+ systems without being modified. Bind every connection the tool's steps use; to keep the
8396
+ connection a step was authored against, bind it to itself.
8386
8397
  x-celigo-ai-guidance:
8387
8398
  - |-
8388
8399
  Per-consumer overrides applied when the wrapper invokes the underlying Tool.
@@ -8390,10 +8401,10 @@ components:
8390
8401
  imports each reference a `_connectionId`,
8391
8402
  and consumers bind real account connections to those abstract requirements here.
8392
8403
  - |-
8393
- Omit this block (or omit `connections` inside it) when the wrapper inherits the
8394
- Tool's authored connections as-is.
8395
- That's the right default when the Tool was authored against connections the
8396
- consumer also wants to use.
8404
+ The save accepts a wrapper without bindings, but when the Tool's steps use connections
8405
+ its run then fails with `connection_not_overridden`. Write one `connections` entry per
8406
+ connection the Tool's steps use, even when the wrapper keeps the Tool's authored
8407
+ connection (`_id` equal to `_abstractId`); a Tool whose steps use no connection needs none.
8397
8408
  properties:
8398
8409
  connections:
8399
8410
  type: array
@@ -9187,7 +9198,8 @@ components:
9187
9198
  AiAgentConfig:
9188
9199
  type: object
9189
9200
  description: |
9190
- AI Agent configuration used by both AiAgentImport and GuardrailImport (ai_agent type).
9201
+ AI agent configuration for an AiAgentImport. An `ai_agent` guardrail is configured by
9202
+ the guardrail spec's `GuardrailAiAgentConfig` instead, which has no `tools` arrays.
9191
9203
 
9192
9204
  Configures which AI provider and model to use, along with instructions, parameter
9193
9205
  tuning, output format, and available tools. Providers come in two families with
@@ -9460,7 +9472,6 @@ components:
9460
9472
  - gpt-5-mini
9461
9473
  - gpt-5-nano
9462
9474
  - gpt-4.1-mini
9463
- - gpt-4o
9464
9475
  x-celigo-ui-override: Required by the AI agent configuration form. Encoded here to mirror the form so builders produce connectable configurations.
9465
9476
  x-celigo-ai-guidance:
9466
9477
  - |-
@@ -9540,7 +9551,9 @@ components:
9540
9551
  minimum: 100
9541
9552
  maximum: 128000
9542
9553
  default: 5000
9543
- description: Maximum number of tokens in the model's response (server default observed live on create)
9554
+ description: |-
9555
+ Caps the length of the model's response, in tokens. An agent created without it is
9556
+ saved with 5000; raise it for long outputs such as large extractions.
9544
9557
  serviceTier:
9545
9558
  type: string
9546
9559
  enum:
@@ -16185,15 +16198,16 @@ components:
16185
16198
  - filter
16186
16199
  description: |-
16187
16200
  Filter applied to incoming records before they are sent to the destination system.
16188
- Records that match continue through the import; records that don't are silently
16189
- dropped. Filter expressions reference the incoming record's fields.
16201
+ Records that match continue through the import; records that don't skip this import,
16202
+ counted as ignored, and continue to the next step. Filter expressions reference the
16203
+ incoming record's fields.
16190
16204
  allOf:
16191
16205
  - $ref: '#/components/schemas/Filter'
16192
16206
  x-celigo-ai-guidance:
16193
16207
  - |-
16194
16208
  ## IMPORT-SPECIFIC BEHAVIOR
16195
16209
 
16196
- **Pre-Import Filtering**: Filters are applied to incoming records before they are sent to the destination system. Records that don't match the filter criteria are silently dropped and not imported.
16210
+ **Pre-Import Filtering**: Filters are applied to incoming records before they are sent to the destination system. A record that doesn't match is not sent, but it is not removed from the flow: it continues to the next step without this import's response-mapped fields, so a later step that writes those fields needs its own filter.
16197
16211
  traceKeyTemplate:
16198
16212
  type: string
16199
16213
  x-celigo-agent:
@@ -16310,7 +16324,7 @@ components:
16310
16324
  mapping step, on the raw upstream records. Engage when the
16311
16325
  user needs to reshape, validate, filter, or annotate records
16312
16326
  before the mapping sees them (drop archived records,
16313
- normalize date strings, split a record into many). Don't
16327
+ normalize date strings). Don't
16314
16328
  engage for static value substitution or simple field
16315
16329
  renames — mappings handle those.
16316
16330
 
@@ -16586,7 +16600,7 @@ components:
16586
16600
  resultField, ...)
16587
16601
  - ``netsuite_da.lookups`` — NetSuite search (recordType,
16588
16602
  searchField, operator, ...)
16589
- - ``http.lookups`` — HTTP request (method, relativeURI, postBody,
16603
+ - ``http.lookups`` — HTTP request (method, relativeURI, body,
16590
16604
  extract, ...)
16591
16605
  - ``jdbc.lookups`` / ``rdbms.lookups`` — SQL query (query,
16592
16606
  extract, ...)
package/dist/tool.yml CHANGED
@@ -12883,7 +12883,7 @@ components:
12883
12883
  ## EXAMPLES:
12884
12884
  - `{ "UserId": "12345", "Name": "John Doe", "Age": 30, "Preferences": { "Language": "en", "Notifications": true } }`
12885
12885
  examples:
12886
- - '{"id": "{{record.id}}", "name": "{{record.name}}", "total": {{record.total}}}'
12886
+ - '{"id": "{{record.id}}", "name": "{{record.name}}", "total": {{record.total}} }'
12887
12887
  updateExpression:
12888
12888
  type: string
12889
12889
  x-celigo-ui-override: Required by the DynamoDB import form when method is updateItem (dynamodb.updateExpression required, visibleWhen method=updateItem).
@@ -13546,7 +13546,10 @@ components:
13546
13546
  the Import's mapping step runs first and shapes the source record,
13547
13547
  then this template renders against that mapped record.
13548
13548
  Reference the mapped record with the ``record`` root when wrapping it (e.g.
13549
- ``{"requestData": {{{jsonSerialize record}}}}``).
13549
+ ``{"requestData": {{{jsonSerialize record}}} }``).
13550
+ Keep a literal ``}`` apart from a closing ``}}`` or ``}}}`` (a space is enough): the save
13551
+ accepts ``{{{jsonSerialize record}}}}``, but every record then fails with
13552
+ ``handlebars_template_parse_error``.
13550
13553
  Avoid bare ``{{{jsonSerialize record}}}`` with no wrapper — leave the field undefined instead.
13551
13554
  Also avoid wrapping a single post-mapped scalar field in ``jsonSerialize`` (e.g.
13552
13555
  ``{{{jsonSerialize record.<scalar>}}}``) — that pattern is brittle.
@@ -13609,9 +13612,9 @@ components:
13609
13612
 
13610
13613
  Typical shapes:
13611
13614
  - Message-bus envelope:
13612
- ``{"MessageBody": {"class": "EntityUpdate", "payload": {{{jsonSerialize record}}}}}``
13615
+ ``{"MessageBody": {"class": "EntityUpdate", "payload": {{{jsonSerialize record}}} }}``
13613
13616
  - Metadata wrap:
13614
- ``{"batchNumber": "{{timestamp dateTimeFormat CST}}", "interfaceType": "...", "requestData": {{{jsonSerialize record}}}}``
13617
+ ``{"batchNumber": "{{timestamp dateTimeFormat CST}}", "interfaceType": "...", "requestData": {{{jsonSerialize record}}} }``
13615
13618
  - Named single-record array wrap (when destination wants ``[record]`` but each request sends one):
13616
13619
  ``{"products": [{{{jsonSerialize record}}}]}``
13617
13620
 
@@ -13652,7 +13655,7 @@ components:
13652
13655
  current ``{{#each data}}`` item.
13653
13656
 
13654
13657
  Example shape:
13655
- ``{"header": {"sellerId": "{{connection.http.unencrypted.sellerId}}"}, "messages": [{{#each data}}{"sku": "{{sku}}", "qty": {{quantity}}}{{/each}}]}``
13658
+ ``{"header": {"sellerId": "{{connection.http.unencrypted.sellerId}}"}, "messages": [{{#each data}}{"sku": "{{sku}}", "qty": {{quantity}} }{{/each}}]}``
13656
13659
  - |-
13657
13660
  ## Anti-pattern — DO NOT wrap a post-mapped scalar in jsonSerialize
13658
13661
 
@@ -13737,7 +13740,7 @@ components:
13737
13740
  mix the two shapes in one body.
13738
13741
  examples:
13739
13742
  - - '{"name": "{{record.name}}", "email": "{{record.email}}"}'
13740
- - - '{"requestData": {{{jsonSerialize record}}}}'
13743
+ - - '{"requestData": {{{jsonSerialize record}}} }'
13741
13744
  - - '{"values": [{{#each batch_of_records}}{{{jsonSerialize this.record}}}{{#unless @last}},{{/unless}}{{/each}}]}'
13742
13745
  x-celigo-agent:
13743
13746
  - handlebars
@@ -14227,9 +14230,7 @@ components:
14227
14230
 
14228
14231
  The referenced helper bundles the polling config plus a required status
14229
14232
  export (polled to check progress) and a result export (fetches the
14230
- final payload). An import configured with an async helper cannot carry
14231
- its own transform, output filter, or preSavePage hook — put that
14232
- processing in the result export instead.
14233
+ final payload).
14233
14234
  examples:
14234
14235
  - 60a2c4e6f321d800129a1a3c
14235
14236
  x-celigo-agent:
@@ -14313,7 +14314,7 @@ components:
14313
14314
 
14314
14315
  - **Static** — only ``map`` + optional ``default``. No HTTP
14315
14316
  request issued. Use for small controlled vocabularies.
14316
- - **Dynamic** — ``method`` + ``relativeURI`` (+ ``postBody``,
14317
+ - **Dynamic** — ``method`` + ``relativeURI`` (+ ``body``,
14317
14318
  ``headers``, ``extract``). Issues a live HTTP request per
14318
14319
  lookup. Adds one HTTP request per record at runtime — factor
14319
14320
  this into flow design for high-volume syncs.
@@ -14351,14 +14352,18 @@ components:
14351
14352
  inject values from the incoming record — e.g.
14352
14353
  ``/customers?email={{{email}}}`` or
14353
14354
  ``/accounts/{{{accountId}}}``.
14354
- postBody:
14355
+ body:
14355
14356
  type: string
14356
14357
  x-celigo-agent:
14357
14358
  - handlebars
14358
14359
  description: |
14359
- Request body template for POST / PUT / PATCH lookup methods.
14360
- Typically a JSON string with Handlebars placeholders —
14361
- ``{"email":"{{{email}}}"}``. Ignored for GET / DELETE.
14360
+ Request body template for POST / PUT / PATCH lookup methods, typically
14361
+ a JSON string with Handlebars placeholders (``{"email":"{{{email}}}"}``);
14362
+ ignored for GET / DELETE. The record's fields sit at the top level:
14363
+ ``{{email}}`` renders the record's value, while ``{{record.email}}``
14364
+ renders empty.
14365
+ x-celigo-ai-guidance:
14366
+ - 'Put the lookup''s request template here, not in ``postBody``: a ``postBody`` saves without an error but is not kept under ``http.lookups``, so the lookup goes out with no body and the run reports no error.'
14362
14367
  headers:
14363
14368
  type: array
14364
14369
  items:
@@ -16009,9 +16014,9 @@ components:
16009
16014
  line) to the rows that populate the
16010
16015
  subrecord. Typically `$` when the
16011
16016
  subrecord data is carried on the same
16012
- line item (the enclosing
16013
- `lists[].jsonPath` has already selected
16014
- the line). Defaults to `$`.
16017
+ line item (iteration over the sublist
16018
+ has already selected the line).
16019
+ Defaults to `$`.
16015
16020
  mapping:
16016
16021
  type: object
16017
16022
  description: |
@@ -16466,9 +16471,10 @@ components:
16466
16471
  SQL `SELECT` statement that resolves the lookup value.
16467
16472
  Typically returns a single row with a single column; use
16468
16473
  `extract` to pick the column when the query returns multiple.
16469
- Inject values from the incoming record with Handlebars — RDBMS
16470
- queries use triple braces and the `record.` prefix:
16471
- `SELECT id FROM users WHERE email = '{{{record.email}}}'`.
16474
+ Inject values from the incoming record with Handlebars and the
16475
+ `record.` prefix — double braces for strings, which the platform
16476
+ quotes and escapes, and triple braces for numbers:
16477
+ `SELECT id FROM users WHERE email = {{record.email}}`.
16472
16478
  extract:
16473
16479
  type: string
16474
16480
  description: |
@@ -16516,7 +16522,7 @@ components:
16516
16522
  description: |-
16517
16523
  SQL statements to execute; required when queryType is `["per_record"]`, `["per_page"]`, or `["first_page"]`, and typically contains a single statement.
16518
16524
  Each element is a complete SQL statement as a plain string — never a single bare string and never an array of objects (objects cause a Cast error).
16519
- Inject values from the incoming record with Handlebars using the `record.` prefix and triple braces, e.g. `'{{{record.name}}}'` for strings (single-quoted in the SQL) and `{{{record.quantity}}}` for numbers.
16525
+ Inject values from the incoming record with Handlebars using the `record.` prefix: double braces for strings and dates (`{{record.name}}`; the platform quotes and escapes the value) and triple braces for numbers (`{{{record.quantity}}}`).
16520
16526
  Rendering is strict: a reference the render model cannot resolve (a bare `{{name}}` without prefix, or `record.*` when the arriving record is a grouped array) fails the step with `cannot_evaluate_handlebars` — it does not render an empty value.
16521
16527
  `record` and `rows` are aliases chosen by the arriving data's shape: an object record binds `record` (`rows` undefined); a grouped array-record (e.g. upstream `groupByFields`) binds `rows` (`record` undefined) — address grouped rows as `{{rows.0.field}}` or iterate `{{#each rows}}`.
16522
16528
  Double braces (`{{record.field}}`) output the value wrapped in single quotes with embedded quotes doubled, while triple braces output it raw; block helpers such as `{{#each}}` and `{{#if}}` use double braces as normal.
@@ -16530,7 +16536,7 @@ components:
16530
16536
  - CORRECT: ["INSERT INTO users (name, email) VALUES ({{record.name}}, {{record.email}})"]
16531
16537
  - WRONG: "INSERT INTO users ..." (not an array)
16532
16538
  - WRONG: [{"query": "INSERT INTO users ..."}] (objects are invalid — causes Cast error)
16533
- - WRONG: ["INSERT INTO users (name) VALUES ('{{name}}')"] (missing record. prefix — rendering is strict, so the step fails with cannot_evaluate_handlebars)
16539
+ - WRONG: ["INSERT INTO users (name) VALUES ({{name}})"] (missing record. prefix — rendering is strict, so the step fails with cannot_evaluate_handlebars)
16534
16540
  - |-
16535
16541
  ## RDBMS HANDLEBARS SYNTAX
16536
16542
 
@@ -16564,7 +16570,7 @@ components:
16564
16570
  | Numeric column value (INT, DECIMAL, ...) | `{{{record.field}}}` |
16565
16571
  | Stored procedure raw arg (already typed) | `{{{record.field}}}` |
16566
16572
  | Identifier (table/column name) | `{{{record.field}}}` |
16567
- | JSON literal (`PARSE_JSON`/JSONB) | `{{{jsonSerialize record.subobject}}}` |
16573
+ | JSON literal (`PARSE_JSON`/JSONB) | `{{jsonSerialize record.subobject}}` (renders the JSON as a quoted string) |
16568
16574
 
16569
16575
  - **Block helpers** (`{{#each}}`, `{{#if}}`, `{{/each}}`,
16570
16576
  `{{#unless}}`) use double braces as normal — they emit no value.
@@ -16583,7 +16589,7 @@ components:
16583
16589
  - Per-page batch (different Handlebars context — see `queryType: per_page` below): `["{{#each batch_of_records}}UPDATE staging SET done=1 WHERE id={{{this.record.id}}};{{/each}}"]`
16584
16590
  examples:
16585
16591
  - - INSERT INTO orders (id, total) VALUES ({{{record.id}}}, {{{record.total}}})
16586
- - - '{{#each batch_of_records}}UPDATE customers SET name=''{{{record.name}}}'' WHERE id={{{record.id}}};{{/each}}'
16592
+ - - '{{#each batch_of_records}}UPDATE customers SET name={{record.name}} WHERE id={{{record.id}}};{{/each}}'
16587
16593
  queryType:
16588
16594
  type:
16589
16595
  - array
@@ -16612,7 +16618,7 @@ components:
16612
16618
  Prefer the highest-performance type the operation supports: bulk_load (Snowflake, Google BigQuery, Microsoft SQL Server on a cloud connection, Azure Synapse and Amazon Redshift — handles INSERT, upsert via `bulkLoad.primaryKeys`, and custom merge or ignore-existing logic via `bulkLoad.overrideMergeQuery`), then bulk_insert for pure INSERTs, then per_page, then per_record only when the logic cannot be expressed as a batch operation.
16613
16619
  For UPDATE, UPSERT, or ignore-existing logic on databases without bulk_load support, use per_page or per_record with `query` — bulk_insert has no duplicate-checking logic.
16614
16620
  Set a single value; do not combine types or use the legacy INSERT and UPDATE values.
16615
- per_page statements render against the whole batch (`batch_of_records`) rather than a single record — loop with `{{#each batch_of_records}}...{{{record.fieldName}}}...{{/each}}`.
16621
+ per_page statements render against the whole batch (`batch_of_records`) rather than a single record — loop with `{{#each batch_of_records}}...{{record.fieldName}}...{{/each}}`, with the same quoting as `query` (double braces for strings, triple for numbers).
16616
16622
 
16617
16623
  `bulk_load` — Stages the records as files and loads them with the database's native COPY / bulk mechanism for maximum throughput; supports INSERT, upsert via bulkLoad.primaryKeys, and custom merge or ignore-existing logic via bulkLoad.overrideMergeQuery; available on Snowflake, Google BigQuery, Microsoft SQL Server (cloud connections), Azure Synapse and Amazon Redshift (NetSuite Analytics Warehouse has it through the JDBC import). The import form calls it "Use optimized bulk load (recommended for larger imports)" and, beside it, calls bulk_insert "Use batch insert SQL query".
16618
16624
  `bulk_insert` — Batch INSERT via multi-row VALUES clause for efficient bulk data loading; has no upsert or ignore-existing logic and is available for all RDBMS types.
@@ -16659,7 +16665,7 @@ components:
16659
16665
  Prompt: "Import customers, ignore existing based on email"
16660
16666
  ```json
16661
16667
  "queryType": ["per_record"],
16662
- "query": ["INSERT INTO customers (name, email) VALUES ('{{{record.name}}}', '{{{record.email}}}')"]
16668
+ "query": ["INSERT INTO customers (name, email) VALUES ({{record.name}}, {{record.email}})"]
16663
16669
  ```
16664
16670
 
16665
16671
  ### Pure INSERT (no duplicate checking)
@@ -16673,7 +16679,7 @@ components:
16673
16679
  Prompt: "Update inventory counts"
16674
16680
  ```json
16675
16681
  "queryType": ["per_record"],
16676
- "query": ["UPDATE inventory SET qty = {{{record.qty}}} WHERE sku = '{{{record.sku}}}'"]
16682
+ "query": ["UPDATE inventory SET qty = {{{record.qty}}} WHERE sku = {{record.sku}}"]
16677
16683
  ```
16678
16684
 
16679
16685
  ### Run Once Per Page
@@ -16681,7 +16687,7 @@ components:
16681
16687
  ```json
16682
16688
  "queryType": ["per_page"]
16683
16689
  ```
16684
- **per_page uses a different Handlebars context than per_record.** The context is the entire batch (`batch_of_records`), not a single `record.` object. Loop through with `{{#each batch_of_records}}...{{{record.fieldName}}}...{{/each}}`.
16690
+ **per_page uses a different Handlebars context than per_record.** The context is the entire batch (`batch_of_records`), not a single `record.` object. Loop through with `{{#each batch_of_records}}...{{record.fieldName}}...{{/each}}`, quoting as in per_record: double braces for strings, triple braces for numbers.
16685
16691
 
16686
16692
  ### Run Once at Start
16687
16693
  Prompt: "Run this cleanup script before processing"
@@ -19641,8 +19647,8 @@ components:
19641
19647
  description: |-
19642
19648
  Configuration for a `ToolImport`, which executes a reusable Celigo Tool resource as the
19643
19649
  import action. The referenced tool defines its own input contract, processing pipeline, and
19644
- output; this object binds the tool to the import and optionally overrides the connections the
19645
- tool uses for this invocation.
19650
+ output; this object binds the tool to the import, along with the connections the tool's steps
19651
+ use for this invocation.
19646
19652
  x-celigo-ai-guidance:
19647
19653
  - |-
19648
19654
  A ToolImport is the **wrapper** that lets a flow / API / another Tool consume a
@@ -19693,7 +19699,8 @@ components:
19693
19699
  Per-import overrides applied to the referenced tool at execution time. Tools use a
19694
19700
  bring-your-own-keys connection model: the tool declares abstract connection slots, and the
19695
19701
  consumer binds concrete connections here so one tool definition can run against different
19696
- systems without being modified. Omit to run the tool with its default connections.
19702
+ systems without being modified. Bind every connection the tool's steps use; to keep the
19703
+ connection a step was authored against, bind it to itself.
19697
19704
  x-celigo-ai-guidance:
19698
19705
  - |-
19699
19706
  Per-consumer overrides applied when the wrapper invokes the underlying Tool.
@@ -19701,10 +19708,10 @@ components:
19701
19708
  imports each reference a `_connectionId`,
19702
19709
  and consumers bind real account connections to those abstract requirements here.
19703
19710
  - |-
19704
- Omit this block (or omit `connections` inside it) when the wrapper inherits the
19705
- Tool's authored connections as-is.
19706
- That's the right default when the Tool was authored against connections the
19707
- consumer also wants to use.
19711
+ The save accepts a wrapper without bindings, but when the Tool's steps use connections
19712
+ its run then fails with `connection_not_overridden`. Write one `connections` entry per
19713
+ connection the Tool's steps use, even when the wrapper keeps the Tool's authored
19714
+ connection (`_id` equal to `_abstractId`); a Tool whose steps use no connection needs none.
19708
19715
  properties:
19709
19716
  connections:
19710
19717
  type: array
@@ -20498,7 +20505,8 @@ components:
20498
20505
  AiAgentConfig:
20499
20506
  type: object
20500
20507
  description: |
20501
- AI Agent configuration used by both AiAgentImport and GuardrailImport (ai_agent type).
20508
+ AI agent configuration for an AiAgentImport. An `ai_agent` guardrail is configured by
20509
+ the guardrail spec's `GuardrailAiAgentConfig` instead, which has no `tools` arrays.
20502
20510
 
20503
20511
  Configures which AI provider and model to use, along with instructions, parameter
20504
20512
  tuning, output format, and available tools. Providers come in two families with
@@ -20771,7 +20779,6 @@ components:
20771
20779
  - gpt-5-mini
20772
20780
  - gpt-5-nano
20773
20781
  - gpt-4.1-mini
20774
- - gpt-4o
20775
20782
  x-celigo-ui-override: Required by the AI agent configuration form. Encoded here to mirror the form so builders produce connectable configurations.
20776
20783
  x-celigo-ai-guidance:
20777
20784
  - |-
@@ -20851,7 +20858,9 @@ components:
20851
20858
  minimum: 100
20852
20859
  maximum: 128000
20853
20860
  default: 5000
20854
- description: Maximum number of tokens in the model's response (server default observed live on create)
20861
+ description: |-
20862
+ Caps the length of the model's response, in tokens. An agent created without it is
20863
+ saved with 5000; raise it for long outputs such as large extractions.
20855
20864
  serviceTier:
20856
20865
  type: string
20857
20866
  enum:
@@ -25054,15 +25063,16 @@ components:
25054
25063
  - filter
25055
25064
  description: |-
25056
25065
  Filter applied to incoming records before they are sent to the destination system.
25057
- Records that match continue through the import; records that don't are silently
25058
- dropped. Filter expressions reference the incoming record's fields.
25066
+ Records that match continue through the import; records that don't skip this import,
25067
+ counted as ignored, and continue to the next step. Filter expressions reference the
25068
+ incoming record's fields.
25059
25069
  allOf:
25060
25070
  - $ref: '#/components/schemas/Filter'
25061
25071
  x-celigo-ai-guidance:
25062
25072
  - |-
25063
25073
  ## IMPORT-SPECIFIC BEHAVIOR
25064
25074
 
25065
- **Pre-Import Filtering**: Filters are applied to incoming records before they are sent to the destination system. Records that don't match the filter criteria are silently dropped and not imported.
25075
+ **Pre-Import Filtering**: Filters are applied to incoming records before they are sent to the destination system. A record that doesn't match is not sent, but it is not removed from the flow: it continues to the next step without this import's response-mapped fields, so a later step that writes those fields needs its own filter.
25066
25076
  traceKeyTemplate:
25067
25077
  type: string
25068
25078
  x-celigo-agent:
@@ -25179,7 +25189,7 @@ components:
25179
25189
  mapping step, on the raw upstream records. Engage when the
25180
25190
  user needs to reshape, validate, filter, or annotate records
25181
25191
  before the mapping sees them (drop archived records,
25182
- normalize date strings, split a record into many). Don't
25192
+ normalize date strings). Don't
25183
25193
  engage for static value substitution or simple field
25184
25194
  renames — mappings handle those.
25185
25195
 
@@ -25455,7 +25465,7 @@ components:
25455
25465
  resultField, ...)
25456
25466
  - ``netsuite_da.lookups`` — NetSuite search (recordType,
25457
25467
  searchField, operator, ...)
25458
- - ``http.lookups`` — HTTP request (method, relativeURI, postBody,
25468
+ - ``http.lookups`` — HTTP request (method, relativeURI, body,
25459
25469
  extract, ...)
25460
25470
  - ``jdbc.lookups`` / ``rdbms.lookups`` — SQL query (query,
25461
25471
  extract, ...)
@@ -30514,7 +30524,7 @@ components:
30514
30524
  (`http.paging.body` likewise from its paging fields). A body that is not parseable JSON at
30515
30525
  rest — Handlebars block helpers outside a string value — renders every field EMPTY in that
30516
30526
  form, so keep templated variables inside a JSON string value:
30517
- `"variables": "{\"after\": {{#if export.http.paging.token}}\"{{export.http.paging.token}}\"{{else}}null{{/if}}}"`.
30527
+ `"variables": "{\"after\": {{#if export.http.paging.token}}\"{{export.http.paging.token}}\"{{else}}null{{/if}} }"`.
30518
30528
  - |-
30519
30529
  The GraphQL form has no relative URI field: the connection `baseURI` is expected to be the
30520
30530
  GraphQL endpoint (a saved `relativeURI` still applies but is not shown). Create GraphQL
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@celigo/api-specs",
3
- "version": "0.2.131",
3
+ "version": "0.2.133",
4
4
  "private": false,
5
5
  "description": "Public OpenAPI bundles (dist/) and the celigo-cli lint schema pack (schemas.json).",
6
6
  "keywords": [
package/schemas.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "provenance": {
3
3
  "repo": "celigo/integrator-api-specs",
4
- "iasCommit": "a1fc60f9",
4
+ "iasCommit": "60c8d128",
5
5
  "generatedAt": "2026-10-21"
6
6
  },
7
7
  "roots": {
@@ -6674,13 +6674,13 @@
6674
6674
  "p": {
6675
6675
  "_lookupCacheId": 1,
6676
6676
  "allowFailures": 118,
6677
+ "body": 1,
6677
6678
  "default": 88,
6678
6679
  "extract": 1,
6679
6680
  "headers": 260,
6680
6681
  "map": 117,
6681
6682
  "method": 164,
6682
6683
  "name": 1,
6683
- "postBody": 1,
6684
6684
  "relativeURI": 1,
6685
6685
  "useDefaultOnMultipleMatches": 9
6686
6686
  }