> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Connecting your own API

> Upload your service's OpenAPI document to Flowker and call its operations from a workflow node. Register the document, point a provider configuration at it, and address one operation per node.

Flowker ships connectors for the services in its catalog. When the service you want to call is your own — an internal API, a partner API, anything with a published OpenAPI document — you upload that document and a workflow node calls its operations directly.

You do this once per document: upload it, create one provider configuration that points at it, then address one operation from each node that calls the service.

## Before you begin

***

* Your service's OpenAPI 3.x document as a file, at most 8 MiB, declaring at least one operation.
* The credentials your service requires, and the authentication method it expects. See [Authentication](/en/flowker/integration-guide#authentication) for the methods Flowker supports.
* A deployment whose schema registry has blob storage configured. `SCHEMA_REGISTRY_S3_BUCKET` holds the OpenAPI documents you upload — see [Flowker environment variables](/en/flowker/flowker-environment-variables).
* A workflow in `draft` status to edit. An active workflow is locked, so call [Move a workflow to draft](/en/reference/flowker/move-workflow-to-draft) first and activate it again afterwards.

<Tip>
  The Lerian Console covers the same path. **Providers → + New Provider → Add your own API** selects an uploaded document and sets the base URL and the authentication — see [Adding a provider](/en/flowker/console/adding-a-provider).
</Tip>

## Step 1: Upload the OpenAPI document

***

<Steps>
  <Step title="Send the file">
    Call [Upload an OpenAPI schema](/en/reference/flowker/upload-openapi-schema) as `multipart/form-data` with three parts: the `file`, a `name`, and a `version`.

    ```bash theme={null}
    curl -X POST https://your-flowker-host/v1/openapi-schemas \
      -H "Authorization: Bearer $TOKEN" \
      -F "file=@acme-kyc.json" \
      -F "name=acme-kyc" \
      -F "version=v1.0.0"
    ```
  </Step>

  <Step title="Keep the id">
    The `201` response describes what Flowker read out of the file. Its `id` is the value every later step references.

    | Field                     | What it tells you                                                                      |
    | ------------------------- | -------------------------------------------------------------------------------------- |
    | `id`                      | The document's identifier. A provider configuration and a webhook trigger point at it. |
    | `name`, `version`         | The pair you sent.                                                                     |
    | `title`                   | The `info.title` of the document.                                                      |
    | `openapiVersion`          | The `openapi` version the document declares.                                           |
    | `operationCount`          | How many path-and-method operations the document declares.                             |
    | `contentHash`, `byteSize` | The stored file's digest and size.                                                     |
    | `createdBy`, `createdAt`  | Who uploaded it and when.                                                              |
  </Step>
</Steps>

### What a stored document is keyed by

`name` and `version` are yours to choose, up to 255 characters each. The pair is unique in your tenant: uploading the same `name` and `version` again answers `FLK-0812`. The `id` Flowker returns is a fresh UUID for each upload, and it is what everything else references — never the name or the version.

Flowker parses the file before it stores it. A file that is not an OpenAPI 3.x document, or one that declares no operation, answers `FLK-0900`. A file over 8 MiB answers `FLK-0901`.

Your uploaded documents are yours alone. A document is only visible to the tenant that uploaded it, and an id from another tenant never resolves.

## Step 2: Read the operations you can call

***

<Steps>
  <Step title="List what you have stored">
    [List OpenAPI schemas](/en/reference/flowker/list-openapi-schemas) returns your documents as metadata only, without their content. It is paginated: `limit`, `cursor`, `sortBy` and `sortOrder`, and the response carries `nextCursor` and `hasMore`.
  </Step>

  <Step title="Read one document's operations">
    [Get an OpenAPI schema](/en/reference/flowker/get-openapi-schema) returns the same metadata plus `content` — the stored file — and `operations`, one entry per operation the document declares.

    | Field         | What it tells you                                                            |
    | ------------- | ---------------------------------------------------------------------------- |
    | `path`        | The operation path, exactly as the document writes it, such as `/v1/checks`. |
    | `method`      | The operation's HTTP method.                                                 |
    | `operationId` | The document's `operationId`, when it declares one.                          |
    | `hasRequest`  | Whether the operation declares a JSON request body.                          |
    | `hasResponse` | Whether the operation declares a JSON success response.                      |

    Copy the `path` and the `method` of the operation you want. Step 4 puts them on the node.
  </Step>

  <Step title="Read one operation's field names">
    [Derive an operation schema](/en/reference/flowker/derive-openapi-operation-schema) takes a `path` and a `method` and returns `inputSchema` — the operation's request body — and `outputSchema` — its success response. It also returns `params`, one entry per parameter the operation declares, each with its `name`, its `in` location and whether it is `required`.

    Those are the field names you write as mapping targets and sources in Step 4. Both query parameters are required, and `method` is case-insensitive and must be one of `GET`, `PUT`, `POST`, `DELETE`, `OPTIONS`, `HEAD`, `PATCH` or `TRACE`; a missing `path` or an unrecognised `method` answers `FLK-0304`. A path and method the document does not declare answers `FLK-0902`.
  </Step>
</Steps>

## Step 3: Point a provider configuration at the document

***

Call [Create a provider configuration](/en/reference/flowker/create-provider-configuration) with `kind` set to `external_openapi`. That kind is the bring-your-own-OpenAPI connection: it references your uploaded document instead of a catalog provider.

| Field                      | Required | Description                                                                                                                                                                                                                                          |
| -------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `kind`                     | Yes      | `"external_openapi"`. You choose the kind when you create the configuration, and it stays the kind the configuration was created with.                                                                                                               |
| `providerId`               | No       | Omit it — this connection targets your own document, not a catalog provider. A read of the configuration then returns the reserved id `external.openapi`.                                                                                            |
| `name`                     | Yes      | A name for this connection, 1–100 characters.                                                                                                                                                                                                        |
| `config.openapi_schema_id` | Yes      | The `id` from [Step 1](#step-1-upload-the-openapi-document). It must name a document in your tenant.                                                                                                                                                 |
| `config.base_url`          | No       | The scheme, host and path prefix Flowker sends requests to. Omit it to use the first usable `servers` entry of the document.                                                                                                                         |
| `config.auth`              | No       | A `{ type, config }` authentication block, in the same shape every provider configuration uses. See [Authentication](/en/flowker/integration-guide#authentication) for each type and its fields. Omit it for a service that needs no authentication. |
| `allowedHosts`             | No       | The hosts this configuration is allowed to call. Omit it, or send an empty list, to accept any public host.                                                                                                                                          |
| `allowedPrivateHosts`      | No       | Named private hosts this configuration is allowed to reach. Cloud metadata and link-local addresses stay blocked.                                                                                                                                    |
| `schemaBindings`           | No       | The stored documents this configuration binds to. See [Bind the document](#bind-the-document).                                                                                                                                                       |
| `description`              | No       | Free text, up to 500 characters.                                                                                                                                                                                                                     |
| `metadata`                 | No       | Your own key-value pairs.                                                                                                                                                                                                                            |

### Where the credential goes

The secret inside `config.auth` is write-only. Flowker sends it to your secrets backend, removes it from the configuration document before it saves the document, and resolves it from the backend at execution time. No provider configuration route returns it. Anything else you place in the configuration document is stored with the configuration, and a read can return it — so put each credential in `config.auth`.

To rotate a secret later, send the new value in an update. To keep the current one, omit the field or send it blank while `auth.type` stays the same — see [Authentication](/en/flowker/integration-guide#authentication).

### Where the host allow-lists are set

Both allow-lists belong to this create call, and to [Update a provider configuration](/en/reference/flowker/update-provider-configuration) afterwards. `allowedHosts` names the hosts every node that calls through this configuration may reach; Flowker checks the request URL and each redirect hop against it at run time. An entry with a leading dot matches subdomains, so `.acme-kyc.example.com` matches `api.acme-kyc.example.com`. Entries are host names only, with no IP literal, no wildcard and no port.

`allowedPrivateHosts` is the companion list for a service that lives on a private network. An entry lets this configuration reach a host that resolves to a private or loopback address, which Flowker blocks by default. Cloud metadata and link-local addresses stay blocked, and no entry reaches them.

### Bind the document

Add a `schemaBindings` entry for the document you referenced. Each entry names one stored document: `type` is `"openapi"`, `schemaId` is the same id you put in `config.openapi_schema_id`, and the optional `operations` array restricts the binding to the operations your workflows actually call.

The binding is what makes the document's dependants visible. With it, [List resources referencing an OpenAPI schema](/en/reference/flowker/list-openapi-schema-references) reports this configuration, and a delete of the document is refused while the configuration is active — see [Removing a document](#removing-a-document).

Flowker resolves every binding when you save. A `schemaId` that names no document in your tenant answers `FLK-0942`, and an `operations` entry the document does not declare answers `FLK-0943`, each naming the failing entry. A malformed entry — an unknown `type`, a `schemaId` that is not a UUID, `operations` on a binding that is not `openapi`, or an operation with no path or method — answers `FLK-0293`.

<Accordion title="Example request">
  ```json theme={null}
  POST /v1/provider-configurations

  {
    "name": "Acme KYC production",
    "description": "Production KYC checks",
    "kind": "external_openapi",
    "config": {
      "openapi_schema_id": "018f3e2a-1c4d-7b9e-a1b2-c3d4e5f6a7b8",
      "base_url": "https://api.acme-kyc.example.com",
      "auth": {
        "type": "api_key",
        "config": {
          "key": "sk-live-xxx",
          "header_name": "X-API-Key",
          "location": "header"
        }
      }
    },
    "allowedHosts": ["api.acme-kyc.example.com"],
    "schemaBindings": [
      {
        "type": "openapi",
        "schemaId": "018f3e2a-1c4d-7b9e-a1b2-c3d4e5f6a7b8",
        "operations": [
          { "path": "/v1/checks", "method": "POST" },
          { "path": "/v1/checks/{checkId}", "method": "GET" }
        ]
      }
    ]
  }
  ```

  The response returns the new configuration's `id`. Keep it — [Step 4](#step-4-address-an-operation-from-a-workflow-node) puts it in the `providerConfigId` of every node that calls this service.
</Accordion>

Flowker checks the configuration before it stores it. A `config` with no `openapi_schema_id`, or one whose value is not a UUID, answers `FLK-0946`. An id that names no document in your tenant answers `FLK-0947`. A `config.auth` block Flowker cannot read — an unknown type, or a type missing one of its required fields — answers `FLK-0948`. No network call is made at this point.

## Step 4: Address an operation from a workflow node

***

An executor node names one operation of the document with two fields in its `data`, alongside the `providerConfigId` of the configuration from Step 3.

| Field              | Required | Description                                                                                                                            |
| ------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `providerConfigId` | Yes      | The UUID of the provider configuration that points at the document.                                                                    |
| `operation_path`   | Yes      | The operation path, exactly as the document writes it, including its `{...}` parameter templates.                                      |
| `operation_method` | Yes      | The operation's HTTP method. Matching is case-insensitive.                                                                             |
| `inputMapping`     | No       | Moves values from the workflow context into the request. Each `target` is a path in the operation's request body, or a parameter name. |
| `outputMapping`    | No       | Moves values out of the response for later nodes to read.                                                                              |

Do not send `executorId` on such a node. Flowker resolves the provider configuration, recognises the kind, and fills the field in for you before it validates the workflow. Every other node field behaves as [Reference the provider configuration from a workflow node](/en/flowker/integration-guide#step-3-reference-the-provider-configuration-from-a-workflow-node) describes.

### How the request is assembled

Flowker reads the operation out of the stored document at run time and builds the request from it:

* **The destination** is `config.base_url` when the configuration sets it, otherwise the first usable `servers` entry of the document, joined with `operation_path`.
* **A `path` parameter** takes its value from the node's resolved data first, and from the request body second. Every `path` parameter needs a value.
* **A `query` or `header` parameter** resolves the same way, and is left out when no value is found.
* **The request body** is what your `inputMapping` builds. Write each `target` exactly as the operation's request schema names it — there is no wrapper object and no prefix to add. [Working with request and response data](/en/flowker/working-with-request-and-response-data) covers mappings and transformations in full.

<Accordion title="Example — a workflow that calls two operations of the document">
  ```json theme={null}
  POST /v1/workflows

  {
    "name": "kyc-check",
    "description": "Opens a KYC check on the Acme API and records the result.",
    "nodes": [
      {
        "id": "kyc-received",
        "type": "trigger",
        "name": "KYC request received",
        "position": { "x": 0, "y": 0 },
        "data": {
          "triggerType": "webhook",
          "path": "kyc/requested",
          "method": "POST",
          "input_contract": "open",
          "format": "json"
        }
      },
      {
        "id": "open-check",
        "type": "executor",
        "name": "Open KYC check",
        "position": { "x": 200, "y": 0 },
        "data": {
          "providerConfigId": "019c96a0-0ac0-7de9-9f53-9cf842a2ee5a",
          "operation_path": "/v1/checks",
          "operation_method": "POST",
          "inputMapping": [
            { "source": "workflow.documentNumber", "target": "documentNumber" },
            { "source": "workflow.fullName", "target": "fullName" }
          ],
          "outputMapping": [
            { "source": "body.checkId", "target": "checkId" },
            { "source": "body.status", "target": "status" }
          ]
        }
      },
      {
        "id": "record-check",
        "type": "action",
        "name": "Record the check",
        "position": { "x": 400, "y": 0 },
        "data": {
          "actionType": "set_output",
          "output": {
            "checkId": "${open-check.checkId}",
            "status": "${open-check.status}"
          }
        }
      }
    ],
    "edges": [
      { "id": "e1", "source": "kyc-received", "target": "open-check" },
      { "id": "e2", "source": "open-check", "target": "record-check" }
    ]
  }
  ```

  The `open-check` node sends `POST https://api.acme-kyc.example.com/v1/checks` with the body its `inputMapping` built. Its `outputMapping` lifts two response fields, so the next node reads `${open-check.checkId}`.

  A node that calls `GET /v1/checks/{checkId}` instead reads the parameter from the same node scope. Map a value onto `checkId`, and Flowker substitutes it into the path.
</Accordion>

<Tip>
  A webhook trigger can validate the inbound payload against one operation of the same document. Set `input_contract` to `"openapi"` and give the trigger `openapi_schema_id`, `operation_path` and `operation_method` — see [Configuring a webhook trigger](/en/flowker/configuring-a-webhook-trigger).
</Tip>

## Step 5: Run it and confirm it worked

***

<Steps>
  <Step title="Activate the workflow">
    Call [Activate a workflow](/en/reference/flowker/activate-workflow). Activation registers the webhook route and resolves what the trigger's contract references.
  </Step>

  <Step title="Run it">
    Call [Execute a workflow](/en/reference/flowker/execute-workflow) with a fresh `Idempotency-Key` header, or send a request to the webhook route.
  </Step>

  <Step title="Read the step results">
    A node that reached your service records the response under its own id. With an `outputMapping`, the mapped names sit directly under that id — `open-check.checkId`. With no `outputMapping`, the node's output keeps the response envelope, so the response body sits one level down, under `body`.
  </Step>
</Steps>

## Publishing a new version of your document

***

A stored document does not change. To ship a revision, upload the file again under a new `version`; that gives you a second stored document with its own `id`.

Nothing switches over on its own. Every reference is by `id`, so a workflow that is already running keeps calling the document it references. To move it, send the provider configuration's `config` with the new `openapi_schema_id` through [Update a provider configuration](/en/reference/flowker/update-provider-configuration). `config` replaces the stored map rather than merging into it, so include `base_url` and `auth` in the same call. Flowker revalidates the new id against your tenant, and answers `FLK-0947` when it does not resolve.

Check [List resources referencing an OpenAPI schema](/en/reference/flowker/list-openapi-schema-references) on the previous document before you retire it — it names everything that still points at it.

## Spec versions for the services in the catalog

***

Flowker's own catalog services resolve against a separate, shared registry of published specs. Three operations manage it. They never touch a document you uploaded in Step 1.

| Operation                                                                           | What it does                                                                                                                                                                                                                    |
| ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [List OpenAPI spec versions](/en/reference/flowker/list-openapi-spec-versions)      | Lists the published versions of a service's spec in `versions`, and reports the one your tenant has pinned in `pinnedVersion`. `pinnedVersion` is empty when your tenant has pinned none.                                       |
| [Pin an OpenAPI spec version](/en/reference/flowker/pin-openapi-spec-version)       | Selects the version your tenant resolves against for that service. It is idempotent: pinning again replaces the version in place. A request missing the service or the version answers `FLK-0801`.                              |
| [Upload an OpenAPI spec version](/en/reference/flowker/upload-openapi-spec-version) | Publishes one version of a service's spec, for every tenant. Versions are immutable: a `service` and `version` pair that already exists answers `FLK-0803`. The caller needs the `create` permission on the `catalog` resource. |

The pin is per tenant. Publishing a version changes nothing for a tenant until that tenant pins it, so a new upload never moves a running workflow onto a different spec. Flowker reads your pinned version when it reports that service's executor schemas in the catalog, so [Get a catalog executor](/en/reference/flowker/get-catalog-executor) describes the version you chose.

## Removing a document

***

<Steps>
  <Step title="Check what would break">
    [List resources referencing an OpenAPI schema](/en/reference/flowker/list-openapi-schema-references) returns two groups, `providerConfigurations` and `workflows`. Both are always present, and each entry carries an `id`, a `name` and a `status`. An entry whose status is active blocks the delete; an inactive one only warns.
  </Step>

  <Step title="Delete it">
    [Delete an OpenAPI schema](/en/reference/flowker/delete-openapi-schema) answers by what still references the document:

    | Outcome               | What it means                                                                                                                                                                                                 |
    | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `204 No Content`      | Nothing referenced the document. It is gone.                                                                                                                                                                  |
    | `200 OK`              | Only inactive referrers held it — a draft or inactive workflow, or a disabled provider configuration. The document is gone, and the body names each one under `warnings` and `providerConfigurationWarnings`. |
    | `409` with `FLK-0945` | An active provider configuration binds the document. Nothing is deleted, and the body lists the referring provider configurations and workflows.                                                              |
    | `409` with `FLK-0936` | An active workflow references the document from a webhook trigger. Nothing is deleted.                                                                                                                        |
  </Step>
</Steps>

To clear a block, disable the provider configuration with [Disable provider configuration](/en/reference/flowker/disable-provider-configuration), or move the workflow to draft with [Move a workflow to draft](/en/reference/flowker/move-workflow-to-draft), then delete the document again.

## What goes wrong

***

| Symptom                                                           | Cause                                                                                             | Fix                                                                                                                                                              |
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| The upload is refused although the file opens in your editor.     | The document declares an `openapi` version outside the 3.x series, or declares no operation.      | Check the `openapi` field and the `paths` object, then upload again.                                                                                             |
| The create call reports the schema id is unknown.                 | The id belongs to another tenant, or the document was deleted.                                    | Call [List OpenAPI schemas](/en/reference/flowker/list-openapi-schemas) and take the id from the response.                                                       |
| The workflow is refused with `FLK-0150`.                          | The node's `providerConfigId` names a configuration that does not exist, or one that is disabled. | Confirm the UUID on the node, and enable the configuration with [Enable provider configuration](/en/reference/flowker/enable-provider-configuration).            |
| The node fails without reaching your service.                     | The operation is absent from the document, or no base URL resolves.                               | Compare `operation_path` and `operation_method` with the `operations` list from Step 2, and set `config.base_url` when the document declares no `servers` entry. |
| The service answers that a required field is missing.             | A mapping `target` does not match the operation's request schema.                                 | Read `inputSchema` from [Derive an operation schema](/en/reference/flowker/derive-openapi-operation-schema) and write each target exactly as it appears there.   |
| The service is never reached and the step reports a rejected URL. | `allowedHosts` does not cover the destination host.                                               | Add the host to `allowedHosts` on the provider configuration.                                                                                                    |

| Error code | When                                                      | What it means                                                                                                                      |
| ---------- | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `FLK-0150` | Create or activate the workflow                           | The node's `providerConfigId` names a configuration that does not exist, or one that is not active.                                |
| `FLK-0812` | Upload                                                    | A document with this `name` and `version` already exists. Choose another version.                                                  |
| `FLK-0900` | Upload                                                    | The file does not parse as an OpenAPI 3.x document, or it declares no operation.                                                   |
| `FLK-0901` | Upload                                                    | The file is over 8 MiB.                                                                                                            |
| `FLK-0811` | Read, derive, delete                                      | The document id does not resolve for your tenant.                                                                                  |
| `FLK-0902` | Derive an operation schema                                | The document declares no operation with that path and method.                                                                      |
| `FLK-0304` | Derive an operation schema                                | The `path` query parameter is missing, or `method` is missing or is not an HTTP method.                                            |
| `FLK-0946` | Create or update the provider configuration               | `config.openapi_schema_id` is missing, or is not a UUID.                                                                           |
| `FLK-0947` | Create or update the provider configuration, and run time | The referenced document does not exist in your tenant.                                                                             |
| `FLK-0948` | Create or update the provider configuration               | The `config.auth` block is malformed.                                                                                              |
| `FLK-0293` | Create or update the provider configuration               | A `schemaBindings` entry is malformed.                                                                                             |
| `FLK-0942` | Create or update the provider configuration               | A `schemaBindings` entry names a document that does not exist in your tenant.                                                      |
| `FLK-0943` | Create or update the provider configuration               | A `schemaBindings` entry restricts to an operation the document does not declare.                                                  |
| `FLK-0949` | Run time                                                  | Neither `config.base_url` nor a usable `servers` entry resolves a base URL. The node fails without calling the service.            |
| `FLK-0950` | Run time                                                  | The bound operation is absent from the document, or a `path` parameter found no value. The node fails without calling the service. |
| `FLK-0945` | Delete the document                                       | An active provider configuration binds it.                                                                                         |
| `FLK-0936` | Delete the document                                       | An active workflow references it from a webhook trigger.                                                                           |
| `FLK-0803` | Upload a spec version                                     | That service and version pair is already published. Versions are immutable.                                                        |
| `FLK-0801` | Pin a spec version                                        | The request is missing the service or the version.                                                                                 |

See the [Flowker error list](/en/reference/flowker/flowker-error-list) for every code.

## What's next

***

<CardGroup cols={2}>
  <Card title="Working with request and response data" icon="arrows-left-right" href="/en/flowker/working-with-request-and-response-data">
    Map values into the operation's request body and read its response back out.
  </Card>

  <Card title="Configuring a webhook trigger" icon="webhook" href="/en/flowker/configuring-a-webhook-trigger">
    Validate an inbound payload against one operation of the same document.
  </Card>

  <Card title="Integration guide" icon="plug" href="/en/flowker/integration-guide">
    Set the authentication, the retries and the circuit breaker every provider configuration shares.
  </Card>

  <Card title="OpenAPI schemas API" icon="code" href="/en/reference/flowker/list-openapi-schemas">
    Explore the schema registry endpoints.
  </Card>
</CardGroup>
