# Marketplace

## Preview a template's installed resource docs

> Returns the concrete resource documents a template would create if\
> installed. The response is an envelope \`{objects, stackRequired}\` where\
> \`objects\` is an array of \`{model, doc}\` entries — one per resource that\
> the install step would materialize.\
> \
> Resource models seen in the wild:\
> \- \`Integration\` — the parent integration doc (always exactly one, first).\
> \- \`Connection\`, \`Export\`, \`Import\`, \`Flow\`, \`Script\` — resource docs,\
> &#x20; pre-filled with the template's config values (references are\
> &#x20; placeholder ids that the installer re-writes during the actual\
> &#x20; install).\
> \
> \`stackRequired\` is \`true\` when the template includes NetSuite-distributed\
> resources that need a dedicated stack — the installer prompts for one\
> before the install proceeds.\
> \
> AI guidance:\
> \- \*\*The id must belong to a Template, not a Connector (Integration App).\*\*\
> &#x20; Calling this endpoint with a Connector id from \`/v1/published\` returns\
> &#x20; 404 \`invalid\_ref "Template not found."\` — pull template ids from the\
> &#x20; \`Template\`-typed entries of \`POST /v1/published/combined\` instead.\
> \- Response is read-only and synthesized fresh each call — no caching\
> &#x20; concerns on the client side.\
> \- Use this before \`POST /v1/integrations/\<id>/install\` flows to show the\
> &#x20; user what they're about to commit to, or to extract individual resource\
> &#x20; docs for programmatic remixing.

```json
{"openapi":"3.1.0","info":{"title":"Marketplace","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"TemplatePreviewResponse":{"type":"object","description":"Envelope describing what a template's install would produce. `objects[]`\nenumerates each resource doc the installer would create, tagged by\n`model`. The docs are populated with the template's defaults and\nplaceholder ids that the installer rewrites during the real install.","properties":{"objects":{"type":"array","description":"Resource docs the installer would materialize. Ordering is\ntypically `Integration` first (exactly one), then `Connection`s,\n`Export`s, `Import`s, `Flow`s, `Script`s.","items":{"type":"object","description":"One resource doc tagged with its model type.","properties":{"model":{"type":"string","enum":["Integration","Connection","Export","Import","Flow","Script"],"description":"Resource class this doc describes."},"doc":{"type":"object","description":"The concrete resource document. Shape matches the write shape\nof the corresponding resource endpoint (e.g. `POST /v1/flows`,\n`POST /v1/exports`, etc.). Fields are populated with the\ntemplate's defaults; ids are placeholders that the installer\nreplaces during the real install.","additionalProperties":true}},"required":["model","doc"]}},"stackRequired":{"type":"boolean","description":"`true` when the template includes NetSuite-distributed resources\nthat need a dedicated stack — the installer prompts for one before\nthe install proceeds. `false` for Shopify / HTTP / file-only\ntemplates."}},"required":["objects","stackRequired"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}}},"paths":{"/v1/templates/{_id}/preview":{"get":{"operationId":"previewTemplate","tags":["Marketplace"],"summary":"Preview a template's installed resource docs","description":"Returns the concrete resource documents a template would create if\ninstalled. The response is an envelope `{objects, stackRequired}` where\n`objects` is an array of `{model, doc}` entries — one per resource that\nthe install step would materialize.\n\nResource models seen in the wild:\n- `Integration` — the parent integration doc (always exactly one, first).\n- `Connection`, `Export`, `Import`, `Flow`, `Script` — resource docs,\n  pre-filled with the template's config values (references are\n  placeholder ids that the installer re-writes during the actual\n  install).\n\n`stackRequired` is `true` when the template includes NetSuite-distributed\nresources that need a dedicated stack — the installer prompts for one\nbefore the install proceeds.\n\nAI guidance:\n- **The id must belong to a Template, not a Connector (Integration App).**\n  Calling this endpoint with a Connector id from `/v1/published` returns\n  404 `invalid_ref \"Template not found.\"` — pull template ids from the\n  `Template`-typed entries of `POST /v1/published/combined` instead.\n- Response is read-only and synthesized fresh each call — no caching\n  concerns on the client side.\n- Use this before `POST /v1/integrations/<id>/install` flows to show the\n  user what they're about to commit to, or to extract individual resource\n  docs for programmatic remixing.","parameters":[{"name":"_id","in":"path","required":true,"description":"Template id from `POST /v1/published/combined`.","schema":{"type":"string","format":"objectId"}}],"responses":{"200":{"description":"Template preview envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplatePreviewResponse"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"description":"No template matched the id. Most commonly: the id belongs to a\nConnector (Integration App) rather than a Template — Connectors are\ninstalled via `/v1/integrations/<id>/install`, not through this\npreview endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```

## List published Integration Apps (Connectors)

> Returns the marketplace catalog of \*\*Integration Apps\*\* — the\
> Celigo-built, fully-managed connectors that install as a single\
> integration. Roughly 30 entries curated by Celigo.\
> \
> Each item is a marketplace listing, not an integration instance —\
> \`\_id\` is the marketplace entry id, the \`applications\` array enumerates\
> the systems the connector bridges, and \`numInstalls\` is the live install\
> counter across all Celigo accounts.\
> \
> AI guidance:\
> \- For a \*\*combined\*\* list that also includes user-installable Templates,\
> &#x20; use \`POST /v1/published/combined\` instead. This endpoint is\
> &#x20; Connector-only.\
> \- Entries here have \*\*no \`docType\` field\*\* — the discriminator only\
> &#x20; appears in the combined endpoint's response.\
> \- Use the \`\_id\` from this endpoint with \`/v1/integrations/\<id>/install\`\
> &#x20; to install a connector, not with \`/v1/templates/\<id>/preview\` (which\
> &#x20; only accepts template ids and 404s on connector ids).

```json
{"openapi":"3.1.0","info":{"title":"Marketplace","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"parameters":{"Include":{"name":"include","in":"query","required":false,"description":"Comma-separated list of fields to project into each returned record.\nTriggers **summary projection** on supported list endpoints: the server\nreturns a minimal identity set for each record (`_id`, `name`, plus a\nresource-specific always-on set like `adaptorType` on exports/imports,\nor richer defaults on `ashares`, `audit`, `httpconnectors`, `transfers`,\netc.) and adds any listed fields that exist on the record. Listed fields\nthe record doesn't carry are silently dropped.\n\nDot notation is supported for projecting nested sub-fields — e.g.\n`include=ftp.directoryPath` on `/v1/exports` returns just that nested\nfield inside `ftp` for FTP-type exports (and omits `ftp` entirely for\nnon-FTP exports).\n\nRules:\n- Value regex is `{a-z A-Z . _}` (letters, dots, underscores) plus the\n  comma separator; digits are also accepted in practice. Any other\n  character returns **400 `invalid_query_params`**.\n- Empty value (`include=`) or bare `include` is ignored — the full\n  default record is returned.\n- `include` and `exclude` are **mutually exclusive**. Passing both\n  returns **400 `invalid_query_params`**: *\"Please provide either\n  include or exclude param in the request query and not both.\"*\n- Array-bracket syntax (`include[]=...`) is not supported and can return\n  a 500.\n- Only list endpoints honor projection — on GET-by-id the parameter is\n  silently ignored.\n- A small set of list endpoints explicitly reject both `include` and\n  `exclude` with **400 `invalid_query_params`** and a message of the form\n  *\"Include or exclude query params are not applicable for `<resource>`\n  resource.\"* Known rejections: `/v1/ediprofiles`, `/v1/environments`,\n  `/v1/iClients`, `/v1/lookupcaches`, `/v1/tags`.","schema":{"type":"string"}},"Exclude":{"name":"exclude","in":"query","required":false,"description":"Comma-separated list of fields to remove from the default response on\nsupported list endpoints. Unlike `include`, `exclude` does NOT trigger\nsummary projection — callers get the standard full-record shape with the\nnamed fields stripped out.\n\nRules:\n- Value regex is `{a-z A-Z . _}` (letters, dots, underscores) plus the\n  comma separator; digits are also accepted in practice. Any other\n  character returns **400 `invalid_query_params`**.\n- Empty value (`exclude=`) is ignored.\n- Certain protected identity fields **cannot be stripped** — e.g.\n  `exclude=name` on `/v1/exports` is silently ignored and `name` remains\n  in the response. Protected sets vary per resource.\n- `include` and `exclude` are **mutually exclusive**. Passing both\n  returns **400 `invalid_query_params`**: *\"Please provide either\n  include or exclude param in the request query and not both.\"*\n- Only list endpoints honor stripping — on GET-by-id the parameter is\n  silently ignored.\n- A small set of list endpoints explicitly reject both `include` and\n  `exclude` with **400 `invalid_query_params`** and a message of the form\n  *\"Include or exclude query params are not applicable for `<resource>`\n  resource.\"* Known rejections: `/v1/ediprofiles`, `/v1/environments`,\n  `/v1/iClients`, `/v1/lookupcaches`, `/v1/tags`.","schema":{"type":"string"}}},"schemas":{"MarketplaceEntry":{"type":"object","description":"A single marketplace listing — either an Integration App (`docType: Connector`)\nor a Template (`docType: Template`). `docType` is only present in\n`POST /v1/published/combined` responses; `GET /v1/published` entries (Connectors\nonly) omit the field.","properties":{"_id":{"type":"string","format":"objectId","description":"Marketplace entry id. For Templates, use this with `/v1/templates/{_id}/preview`."},"name":{"type":"string","description":"Display name of the marketplace entry."},"description":{"type":"string","description":"Marketing description shown in the marketplace listing."},"imageURL":{"type":"string","description":"Relative image path (e.g. `/images/company-logos/amazon-netsuite.png`)\nor absolute URL. Not always present on Template entries."},"websiteURL":{"type":"string","format":"uri","description":"External product page URL. Rare on Template entries."},"applications":{"type":"array","description":"Systems this marketplace entry bridges. Values are either\nwell-known application slugs (`netsuite`, `shopify`, `amazonmws`) or\nobject ids referencing an Application definition.","items":{"type":"string"}},"user":{"type":"object","description":"Publisher metadata.","properties":{"name":{"type":"string","description":"Publisher display name."},"company":{"type":"string","description":"Publisher's company. For Celigo-built content this is `\"Celigo\"`."}}},"trialEnabled":{"type":"boolean","description":"Whether this entry offers a trial install. Populated on Integration\nApp entries; rarely set on Templates."},"lastModified":{"type":"string","format":"date-time","description":"When the marketplace entry was last updated."},"numInstalls":{"type":"integer","description":"Live install counter across all Celigo accounts. Used as the\n`sort_by=numInstalls` key."},"docType":{"type":"string","enum":["Connector","Template"],"description":"Discriminator distinguishing Integration Apps from Templates. Only\npopulated in `POST /v1/published/combined` responses. Absent in\n`GET /v1/published` (Connectors only)."}},"required":["_id","name"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}}},"paths":{"/v1/published":{"get":{"operationId":"listPublishedConnectors","tags":["Marketplace"],"summary":"List published Integration Apps (Connectors)","description":"Returns the marketplace catalog of **Integration Apps** — the\nCeligo-built, fully-managed connectors that install as a single\nintegration. Roughly 30 entries curated by Celigo.\n\nEach item is a marketplace listing, not an integration instance —\n`_id` is the marketplace entry id, the `applications` array enumerates\nthe systems the connector bridges, and `numInstalls` is the live install\ncounter across all Celigo accounts.\n\nAI guidance:\n- For a **combined** list that also includes user-installable Templates,\n  use `POST /v1/published/combined` instead. This endpoint is\n  Connector-only.\n- Entries here have **no `docType` field** — the discriminator only\n  appears in the combined endpoint's response.\n- Use the `_id` from this endpoint with `/v1/integrations/<id>/install`\n  to install a connector, not with `/v1/templates/<id>/preview` (which\n  only accepts template ids and 404s on connector ids).","parameters":[{"$ref":"#/components/parameters/Include"},{"$ref":"#/components/parameters/Exclude"}],"responses":{"200":{"description":"Array of Integration App (Connector) marketplace entries.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MarketplaceEntry"}}}}},"401":{"$ref":"#/components/responses/401-unauthorized"}}}}}}
```

## List Integration Apps and Templates together

> Returns a unified array of \*\*all\*\* marketplace content — both Integration\
> Apps (\`docType: Connector\`) and Templates (\`docType: Template\`). Each\
> entry carries the \`docType\` discriminator so callers can partition.\
> \
> Despite being a POST, this is a \*\*read-only, safe\*\* endpoint — the body\
> is an empty \`{}\` in the default CLI invocation. POST is used purely to\
> carry sort and filter parameters that don't fit cleanly in a query\
> string. \`GET /v1/published/combined\` returns 404 — the route is\
> POST-only.\
> \
> AI guidance:\
> \- Always send \`Content-Type: application/json\` + at least \`{}\` body —\
> &#x20; omitting the header returns \*\*415\*\* "Content-Type should equal\
> &#x20; application/json", not 400.\
> \- \`sort\_by\` accepts only \`numInstalls\`, \`name\`, or \`lastModified\` —\
> &#x20; other values (including \`createdAt\`, \`newest\`) return \*\*400\
> &#x20; \`invalid\_query\_param\`\*\*.\
> \- For Connector-only listings, \`GET /v1/published\` is lighter — use the\
> &#x20; combined endpoint when you need Templates too.\
> \- To preview a Template's installed resources, pipe its \`\_id\` from this\
> &#x20; endpoint into \`GET /v1/templates/{\_id}/preview\` (note: Template ids\
> &#x20; only; Connector ids 404 there).

```json
{"openapi":"3.1.0","info":{"title":"Marketplace","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"MarketplaceEntry":{"type":"object","description":"A single marketplace listing — either an Integration App (`docType: Connector`)\nor a Template (`docType: Template`). `docType` is only present in\n`POST /v1/published/combined` responses; `GET /v1/published` entries (Connectors\nonly) omit the field.","properties":{"_id":{"type":"string","format":"objectId","description":"Marketplace entry id. For Templates, use this with `/v1/templates/{_id}/preview`."},"name":{"type":"string","description":"Display name of the marketplace entry."},"description":{"type":"string","description":"Marketing description shown in the marketplace listing."},"imageURL":{"type":"string","description":"Relative image path (e.g. `/images/company-logos/amazon-netsuite.png`)\nor absolute URL. Not always present on Template entries."},"websiteURL":{"type":"string","format":"uri","description":"External product page URL. Rare on Template entries."},"applications":{"type":"array","description":"Systems this marketplace entry bridges. Values are either\nwell-known application slugs (`netsuite`, `shopify`, `amazonmws`) or\nobject ids referencing an Application definition.","items":{"type":"string"}},"user":{"type":"object","description":"Publisher metadata.","properties":{"name":{"type":"string","description":"Publisher display name."},"company":{"type":"string","description":"Publisher's company. For Celigo-built content this is `\"Celigo\"`."}}},"trialEnabled":{"type":"boolean","description":"Whether this entry offers a trial install. Populated on Integration\nApp entries; rarely set on Templates."},"lastModified":{"type":"string","format":"date-time","description":"When the marketplace entry was last updated."},"numInstalls":{"type":"integer","description":"Live install counter across all Celigo accounts. Used as the\n`sort_by=numInstalls` key."},"docType":{"type":"string","enum":["Connector","Template"],"description":"Discriminator distinguishing Integration Apps from Templates. Only\npopulated in `POST /v1/published/combined` responses. Absent in\n`GET /v1/published` (Connectors only)."}},"required":["_id","name"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}}},"paths":{"/v1/published/combined":{"post":{"operationId":"listPublishedCombined","tags":["Marketplace"],"summary":"List Integration Apps and Templates together","description":"Returns a unified array of **all** marketplace content — both Integration\nApps (`docType: Connector`) and Templates (`docType: Template`). Each\nentry carries the `docType` discriminator so callers can partition.\n\nDespite being a POST, this is a **read-only, safe** endpoint — the body\nis an empty `{}` in the default CLI invocation. POST is used purely to\ncarry sort and filter parameters that don't fit cleanly in a query\nstring. `GET /v1/published/combined` returns 404 — the route is\nPOST-only.\n\nAI guidance:\n- Always send `Content-Type: application/json` + at least `{}` body —\n  omitting the header returns **415** \"Content-Type should equal\n  application/json\", not 400.\n- `sort_by` accepts only `numInstalls`, `name`, or `lastModified` —\n  other values (including `createdAt`, `newest`) return **400\n  `invalid_query_param`**.\n- For Connector-only listings, `GET /v1/published` is lighter — use the\n  combined endpoint when you need Templates too.\n- To preview a Template's installed resources, pipe its `_id` from this\n  endpoint into `GET /v1/templates/{_id}/preview` (note: Template ids\n  only; Connector ids 404 there).","parameters":[{"name":"sort_by","in":"query","required":false,"schema":{"type":"string","enum":["numInstalls","name","lastModified"]},"description":"Sort key. `numInstalls` (descending) matches the CLI default.\nOmitting `sort_by` returns results in server-default order."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Body is required (even if empty) because the endpoint is POST\nand the server enforces `Content-Type: application/json` —\notherwise 415. No fields inside the body are currently honored by\nthe server for filtering."}}}},"responses":{"200":{"description":"Array of marketplace entries, both Connectors and Templates.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MarketplaceEntry"}}}}},"400":{"description":"Typically `invalid_query_param` when `sort_by` is outside the\naccepted enum.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"415":{"description":"Request lacked `Content-Type: application/json`. The server refuses\nto accept the body and returns this even when the body is an empty\nstring.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developer.celigo.com/api/api-reference/marketplace.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
