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.

By celigo · 1,046 installs

npx skills add celigo/ai --skill building-apis

Source repository · Upstream listing

<! 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. The Request IS the Source Record APIs are invoked by an external HTTP caller there is no upstream export, no scheduler, no listener feeding them. That has three design consequences: The request stage is the input shape. Whatever the caller sends (body, path params, query params, headers) is what downstream processing sees as the record. There is no upstream pipeline to reshape it first use the request transform if the envelope needs reshaping before routing. The response stage is the output. Whatever the selected response definition produces is exactly what the caller receives. Nothing runs after it. No self starting. APIs have no schedule , no listener, and none of the flow runtime controls ( proceedOnFailure , skipRetries , chaining). "Every night at 2 AM, do X" is a flow possibly one that calls the API, but the schedule lives on the flow. Retry after failure is the caller's decision. When a flow needs to invoke an API, it does so as an ordinary HTTP caller (an HTTP export/import pointing at the API's URL). There is no special flow step to API wiring. A top level disabled: true takes the API offline without deleting it callers get a 404 until it's re enabled. API Modes Builder Mode ( type: "builder" ) Visual configuration with discrete components: 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 Scenario Mode Why Standard lookup/write with structured response Builder Visual debugging, test runs, structured responses Multiple response shapes based on success/failure Builder Response router + inputFilter handles this declaratively Complex conditional logic or custom auth validation Script Full JavaScript control over request/response Dynamic routing that can't be expressed as input filters Script handleRequest can implement arbitrary logic Proxy through an authenticated connection Builder Wire the connection's export/import as a page processor Simple webhook receiver that transforms and forwards Builder Single router, single branch, one import Minimum Required Fields Mode Required Fields Builder name , type: "builder" , builder.request (method + relativeURI) Script name , type: "script" , script. scriptId , script.function Legacy name , scriptId , function (no type field) Schema Index All schemas are in [references/schemas/](references/schemas/): Schema What it defines [request.yml](references/schemas/request.yml) Top level API fields (name, type, version, disabled, builder/script refs) [response.yml](references/schemas/response.yml) API response shape [builder.yml](references/schemas/builder.yml) Builder configuration (request, routers, responseRouter, responses refs) [api request.yml](references/schemas/api request.yml) Request config (method, relativeURI, params, bodySchema, mockRequest, transform) [api response.yml](references/schemas/api response.yml) Response definitions (id, name, type, statusCode, inputFilter, mappings, hooks) [response router.yml](references/schemas/response router.yml) Response router (id="apiRouter", routeRecordsUsing) [router.yml](references/schemas/router.yml) Routers (branches, inputFilter, pageProcessors) [script.yml](references/schemas/script.yml) Script config ( scriptId, function) [apim.yml](references/schemas/apim.yml) APIM metadata (publication status) [shipworks.yml](references/schemas/shipworks.yml) Legacy ShipWorks auth Related Skills [configuring exports Quick Reference](../configuring exports/SKILL.md quick reference) building lookup exports used as page processors in the API pipeline [configuring imports Quick Reference](../configuring imports/SKILL.md quick reference) building imports used as page processors in the API pipeline [building flows How to Build a Flow](../building flows/SKILL.md how to build a flow) flows share the same router/branch/pageProcessor pipeline mechanics [writing scripts Quick Reference](../writing scripts/SKILL.md quick reference) writing handleRequest (script mode APIs), preMap / postMap hooks, and postResponseMap [writing handlebars Quick Reference](../writing handlebars/SKILL.md quick reference) dynamic expressions in request bodies, URIs, and response mappings [configuring filters Quick Reference](../configuring filters/SKILL.md quick reference) input filters on router branches to conditionally route records <! 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. 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](references/schemas/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]( 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 neve