skillZs
LIVE SKILL TAGS
>>> LIVE SKILLS INDEX <<<
* OPEN SOURCE *
NO LOGIN, NO TRACKING
REAL INSTALL DATA
← back to all skills
celigo/ai180 installs

building-apis

Build Celigo APIs -- custom HTTP endpoints that let external systems push or query data synchronously through Celigo integrations. Use when creating APIs, proxying authenticated requests, or exposing lookup/write operations as a REST interface that returns a structured response.

How do I install this agent skill?

npx skills add https://github.com/celigo/ai --skill building-apis
view source ↗

Is this agent skill safe to install?

  • Gen Agent Trust Hubpass

    This skill provides comprehensive documentation and schema definitions for building APIs on the Celigo platform. It covers both visual 'Builder' and code-based 'Script' modes, detailing how to define requests, routing logic, and structured responses. The skill is informative and does not contain malicious code, data exfiltration patterns, or unauthorized access attempts.

  • Socketpass

    No alerts

  • Snykwarn

    Risk: MEDIUM · 1 issue

What does this agent skill do?

<!-- TIER:1 -->

Building APIs

An API is a RESTful endpoint that exposes integration logic for external consumption. External systems call the API over HTTP; the API processes the request through lookups and imports, then returns a structured response. Concerns when building an API:

  • Mode selection -- builder (visual configuration) vs script (full JavaScript control)
  • Request definition -- HTTP method, URI path, parameters, body schema, request transformation
  • Processing pipeline -- routers and page processors (lookups + imports) that execute business logic
  • Response routing -- directing processed data to the correct response definition based on success/failure or custom conditions
  • Response shaping -- status codes, field mappings, body schema, hooks (preMap, postMap) on each response
  • Response mapping -- extracting fields from each page processor's response back into the record for downstream steps. Configured on each pageProcessors[] entry, same as in flows. For lookup exports the response has data[] and errors[] (use data[0].fieldName for single results). For imports the response is via _json (use _json.fieldName)
  • postResponseMap hook -- JavaScript processing after response mapping, configured on pageProcessors[] entries

Used across integrations alongside flows and tools. APIs do not have their own authentication -- incoming requests authenticate via the Celigo API token; outbound calls to external systems use the connections referenced by exports/imports in the pipeline.

API Modes

Builder Mode (type: "builder")

Visual configuration with discrete components:

API (type: "builder")
+-- request            -- method, relativeURI, params, bodySchema, mockRequest, transform
+-- routers[]          -- processing pipeline (same structure as flow routers)
|   +-- branches[]
|       +-- inputFilter        -- when to use this branch (s-expression rules)
|       +-- pageProcessors[]   -- lookups (exports) and imports
|       +-- nextRouterId       -- chain to next router, or "apiRouter" to finish
+-- responseRouter     -- id="apiRouter", routes processed data to a response
+-- responses[]        -- success, fail, custom -- each with statusCode, inputFilter, mappings

The incoming HTTP request replaces the export as data source. Routers and page processors work identically to flows.

API Execution Pipeline (Builder Mode)

When an API receives a request:

  1. Request received -- method + path matched against the API endpoint definition
  2. Request transform (optional) -- reshapes the incoming request body before routing
  3. Router evaluation -- routeRecordsUsing evaluates branch input filter conditions
  4. Branch selection -- first matching branch processes the request
  5. Page processors -- each processor in the branch executes sequentially (export lookups, import writes)
  6. Response mapping -- responseMapping on each processor carries data forward to the next processor
  7. Response router -- responseRouter (id="apiRouter") selects which response template to use based on response input filters
  8. Response -- selected response template returned to the caller with its statusCode, headers, and body

Script Mode (type: "script")

A single handleRequest JavaScript function receives the request object (method, headers, queryParams, body, pathParams) and returns {statusCode, headers, body}. Complete control with no visual configuration.

Legacy APIs (no type field, top-level _scriptId + function) exist in production but are not represented in the current spec. Distinguish by: if type is absent/null and _scriptId is present, it's legacy.

Quick Reference

Decision Matrix

ScenarioModeWhy
Standard lookup/write with structured responseBuilderVisual debugging, test runs, structured responses
Multiple response shapes based on success/failureBuilderResponse router + inputFilter handles this declaratively
Complex conditional logic or custom auth validationScriptFull JavaScript control over request/response
Dynamic routing that can't be expressed as input filtersScripthandleRequest can implement arbitrary logic
Proxy through an authenticated connectionBuilderWire the connection's export/import as a page processor
Simple webhook receiver that transforms and forwardsBuilderSingle router, single branch, one import

Minimum Required Fields

ModeRequired Fields
Buildername, type: "builder", builder.request (method + relativeURI)
Scriptname, type: "script", script._scriptId, script.function
Legacyname, _scriptId, function (no type field)

Schema Index

All schemas are in references/schemas/:

SchemaWhat it defines
request.ymlTop-level API fields (name, type, version, disabled, builder/script refs)
response.ymlAPI response shape
builder.ymlBuilder configuration (request, routers, responseRouter, responses refs)
api-request.ymlRequest config (method, relativeURI, params, bodySchema, mockRequest, transform)
api-response.ymlResponse definitions (id, name, type, statusCode, inputFilter, mappings, hooks)
response-router.ymlResponse router (id="apiRouter", routeRecordsUsing)
router.ymlRouters (branches, inputFilter, pageProcessors)
script.ymlScript config (_scriptId, function)
apim.ymlAPIM metadata (publication status)
shipworks.ymlLegacy ShipWorks auth

Related Skills

<!-- TIER:2 -->

How to Build an API

1. Plan what the API needs to do

Before creating anything, understand the requirements: what endpoint the caller needs, what data it sends, what systems are involved, what the response should look like. This determines everything -- mode, pipeline shape, which connections/exports/imports are needed.

2. Decide the mode

Use builder for most APIs -- it provides visual debugging, test runs, and structured responses. Use script only when the processing logic is too dynamic for the visual pipeline (e.g., complex conditional responses, custom auth validation, dynamic routing).

3. Check for existing resources

Look for connections, exports, and imports that can be reused before creating new ones.

# Search across all resource types in the account
celigo account search "<keyword>"

# Show what an existing API uses (exports, imports, connections)
celigo account dependencies api <id>

# Find orphaned resources that could be reused
celigo account lint

# Search for APIs already in the account for patterns
celigo apis list | grep -i "<keyword>"

# Check existing exports/imports that could serve as pipeline steps
celigo exports list | grep -i "<system-name>"
celigo imports list | grep -i "<system-name>"

# Search marketplace for pre-built integration templates
celigo templates marketplace

The account index auto-refreshes when stale (>4 hours). Force a fresh snapshot with celigo account snapshot.

4. Create the supporting resources (bottom-up)

APIs reference exports and imports as page processors -- these must exist before you can attach them. Build order:

  1. Connections -- create or reuse connections to the target systems
  2. Exports -- for lookups that query external systems (use configuring-exports skill)
  3. Imports -- for writes to external systems (use configuring-imports skill)

5. Define the request (builder mode)

Choose the HTTP method and URI path. GET and POST are most common; PUT and PATCH are rare.

  • Path parameters use colon notation: /customers/:id
  • Document query parameters, path parameters, headers, and body schema
  • Add a mockRequest for testing the pipeline without live calls
  • Optionally add a request transform (expression-based or script-based) to reshape incoming data before processing

6. Build the processing pipeline

The pipeline is made of routers, branches, and page processors. See router.yml for the full schema.

Every builder API needs at least one router -- it's the container that holds branches, and branches hold the page processors that do the actual work. Use multiple branches when different request conditions need different processing paths (e.g., branch by HTTP method, request field value, or record type). Use multiple routers when you need sequential stages of processing where each stage can branch independently.

For pass-through routers (single branch, no filters, just linear steps before a branching router), omit routeRecordsTo and routeRecordsUsing -- including them makes it appear as a filter-based branch in the UI. The API defaults are sufficient.

Input filters use s-expression syntax: ["operator", ["type", ["extract", "field"]], value]. Type wrappers (string, number, boolean) are required around extract and context accessors. Logical combinators: ["and", cond1, cond2], ["or", cond1, cond2].

The last branch in the chain must set nextRouterId: "apiRouter" to reach the response router.

7. Configure responses

Every builder API needs exactly one success response and one fail response. Add custom responses for specific scenarios (e.g., 404 not found, 422 validation error).

Each response has:

  • statusCode (HTTP status code)
  • inputFilter to determine when it's selected (typically ["equals", ["boolean", ["context", "success"]], true] for success)
  • mappings to shape the response body from the processed record
  • Optional bodySchema for documentation, headers, lookups, and hooks (preMap, postMap)

8. Configure the response router

Set id: "apiRouter" and choose routing method:

  • input_filters (default) -- evaluates each response's inputFilter
  • script -- custom JavaScript returns the response id to use

9. Build the JSON

Reference the Schema Index above for exact field schemas.

Every API needs at minimum: name, type, and either builder (with request) or script (with _scriptId and function).

The Response and Routing Model

Once the routers finish processing, the API selects which response to return and shapes its body. This is where APIs diverge most from flows -- the routing is narrower, and "mapping" happens at two distinct layers.

Branch selection and router chaining

APIs support a single routing strategy: first_matching_branch. Within a router, each record is evaluated against the branches in order and taken by the first branch whose inputFilter matches; that record then follows only that branch. (Flows also offer all_matching_branches, which fans one record out to every matching branch -- APIs never do this. A record takes exactly one branch per router.)

Each branch's nextRouterId decides where the record goes after that branch's page processors finish:

  • Another router's id -- chain into that router for a further stage of processing.
  • "apiRouter" -- hand off to the response router (whose reserved id is always apiRouter) to finish.

Chaining lets you express sequential stages where each stage branches independently; the last branch in the chain sets nextRouterId: "apiRouter" to reach the response router.

Response selection -- success, fail, custom

Every builder API has exactly one success response, exactly one fail response, and zero or more custom responses (the response's type field). The response router (id: "apiRouter") picks one after processing completes:

  • success -- the happy path, returned when processing completed and no custom response matched. Conventionally a 2xx statusCode (200, or 201 when the API created something).
  • fail -- the error path. Processing errors (a lookup returned a 500, an import got a 4xx, a script threw) are routed here automatically. Conventionally a 4xx/5xx statusCode (400 or 500); its mappings surface the error message and any context the caller needs.
  • custom -- a non-error, non-default response selected by its own inputFilter. Reach for one when the outcome fits neither success nor fail, when the statusCode differs, or when the body shape differs. Typical cases:
    • 404 not found -- the lookup ran but returned zero records (filter: the results array is empty).
    • 409 conflict -- the destination rejected a create because the record already exists.
    • 202 accepted -- processing started a background job; tell the caller "received, working on it."
    • Conditional body -- a different shape driven by a query parameter (e.g. ?format=summary vs ?format=full).

In input_filters mode the response router returns the first response whose inputFilter matches, so list custom responses ahead of success to let their specific conditions win. In script mode a JavaScript function inspects the record and returns the response id to use.

statusCode vs the response type

These are independent and often conflated:

  • The response type (success / fail / custom) is Celigo's internal classification -- it drives which response the response router selects.
  • The statusCode is the HTTP status the caller receives -- it lives on the response definition.

A custom response can carry any statusCode (the "not found" response returns 404; the "async accepted" response returns 202), and success is conventionally 2xx but doesn't have to be. So "return a 404 when the customer isn't found" means adding a custom response with statusCode: 404 and an inputFilter that matches when the lookup's results array is empty -- not editing the success response.

The two mapping layers

"Mapping" refers to two different things at two layers, and conflating them is the most common source of confusion when building APIs.

1. Page-processor responseMapping (record enrichment). Configured on a lookup or import inside a router branch -- the same shape as a flow's page-processor responseMapping. It pulls fields off that page processor's response and merges them onto the record so downstream routers, page processors, and response mappings can see them. It does not shape the HTTP body.

{
  "fields": [
    {"extract": "id", "generate": "customerId"},
    {"extract": "accountStatus", "generate": "status"}
  ]
}

2. Response-stage mappings (HTTP body). Configured on a success / fail / custom response (alongside its lookups and hooks). It reads the now-enriched record and builds the HTTP response body returned to the caller.

{
  "mappings": [
    {"extract": "customerId", "generate": "data.id"},
    {"extract": "status", "generate": "data.status"}
  ]
}

The two work together: the lookup's responseMapping merges customerId onto the record, then the response's mappings place customerId into the body's data.id. A field the page processor returned must first be carried onto the record by a responseMapping before a response mapping can extract it. When unsure which layer you need, ask: does this step add the field to the record (page-processor responseMapping) or read the field off the record into the body (response mappings)?

CLI Commands

# CRUD
celigo apis list
celigo apis get <id>
celigo apis create < api.json
celigo apis update <id> < api.json
celigo apis set <id> key=value [key2=value2 ...]
celigo apis delete <id>

# Clone (builder-mode only)
celigo apis clone <id> --api-version <version> [--name <name>] [--description <desc>] [--environment <envId>]

# Pipeline management
celigo apis add-processor <id> <exportOrImportId> [--router <routerId>] [--branch <branchName>]
celigo apis remove-processor <id> <exportOrImportId> [--router <routerId>] [--branch <branchName>]

# Logs
celigo apis logs <id>
celigo apis log-detail <id> <key>

# Test run
celigo apis test-run <id>
celigo apis test-run-step-results <id> <runId> <exportOrImportId>
celigo apis test-run-step-logs <id> <runId> <exportOrImportId>

# Debug (for exports/imports within the API pipeline)
celigo apis debug-requests <id> <exportOrImportId> [--since <minutes>]
celigo apis debug-request-detail <id> <exportOrImportId> <key>

# Discovery
celigo account search "<keyword>"
celigo templates marketplace
<!-- TIER:3 -->

Pre-Submit Checklist

Before creating or updating an API, verify:

  • name is set and descriptive
  • type is "builder" or "script" (not omitted, which creates a legacy API)
  • Builder mode: builder.request.method and builder.request.relativeURI are set
  • Builder mode: at least one router with at least one branch exists
  • Builder mode: last branch has nextRouterId: "apiRouter"
  • Builder mode: both success and fail responses are defined
  • Builder mode: success response inputFilter uses ["equals", ["boolean", ["context", "success"]], true]
  • Script mode: script._scriptId and script.function reference a valid script
  • All _exportId and _importId references in page processors point to existing resources
  • Router IDs are unique within the API
  • version is set (it becomes part of the endpoint URL: /{version}{relativeURI})
  • Input filter expressions wrap extract/context accessors in type wrappers (string, number, boolean)

Gotchas

  1. PUT erases omitted fields. Always GET first, modify, then PUT. The set command handles this automatically.
  2. APIs only support first_matching_branch routing. Unlike flows which also support all_matching_branches, API routers always stop at the first matching branch.
  3. Omitting inputFilter type wrappers silently fails. Use ["boolean", ["context", "success"]], not bare ["context", "success"] -- the filter will never match without the wrapper.
  4. Clone only works for builder-mode APIs. Script and legacy APIs cannot be cloned via the CLI.
  5. Missing a success or fail response causes undefined behavior. The response router won't know where to route.
  6. **version becomes part of the URL path.** The full endpoint is /{version}{relativeURI}. Changing the version changes the URL that callers must use.
  7. Page-processor responseMapping and response mappings are different layers. responseMapping enriches the record with fields from a page processor's response; a response's mappings shape the HTTP body from that record. A field the lookup returned won't reach the body unless a responseMapping first carries it onto the record.

Common Errors

ErrorCauseFix
404 on API endpointWrong version or relativeURI in the requestVerify the full URL is /{version}{relativeURI} and both match the API definition
422 validation error on create/updateMissing required fields or invalid field valuesCheck the Pre-Submit Checklist; verify type is set
Response always returns the fail responseSuccess inputFilter is malformed or missing type wrapperUse ["equals", ["boolean", ["context", "success"]], true] exactly
Response body is emptyResponse mappings not configured or field paths don't matchVerify mapping extract paths match the actual processed record structure
Pipeline step silently skippedinputFilter on a branch evaluates to false for all recordsDebug with celigo apis test-run-step-results to see each step's input/output
Clone failed errorAttempting to clone a script-mode or legacy APIClone is builder-mode only; recreate script APIs manually
Page processor returns no dataExport/import _id reference is wrong or resource is disabledVerify the referenced resource exists and is enabled with celigo exports get / celigo imports get
Router ID not found errornextRouterId references a non-existent router IDEnsure all nextRouterId values match a real router id or "apiRouter"
Response body missing a field the lookup returnedThe page-processor responseMapping never carried the field onto the recordAdd a responseMapping entry ({"fields": [{"extract": ..., "generate": ...}]}) on the page processor so the response mappings have it to extract

Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.

<a href="https://skillzs.dev/skills/celigo/ai/building-apis">View building-apis on skillZs</a>