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

# Introduction

> Author custom integrations for your organization entirely through the API

## Overview

The Integrations API lets you register your own integrations in Opus programmatically — the provider they belong to, the integration itself with the actions it can perform, and the credential schema it authenticates with.

These endpoints author the integration **catalog**: the definition of an integration and the shape of its credentials, shared across your whole organization. Connecting an integration inside a workspace — supplying the real secret values — is a separate, workspace-scoped step done in the Opus app.

## Base URL

All API requests should be made to the following base URL:

```
https://operator.opus.com/api/v1/integration/
```

## Authentication

All API endpoints require authentication with your Opus API key, sent in the `x-service-key` header.

```text theme={null}
x-service-key: <your_api_key>
```

Your key determines your identity and your organization. Every endpoint here requires the **Integration: Full** permission **at organization level** — a workspace-level grant is not sufficient, because everything you create belongs to the organization rather than to a workspace.

A request with a missing, invalid, or expired key returns `401`. Keys are rate limited — sustained bursts return `429`.

<Note>
  Your API key is a unique, secret credential. Store it securely and never expose it in client-side code.
</Note>

<Warning>
  Your organization must be **verified** to author integrations. An unverified organization receives `403` from every endpoint in this section. Contact Opus support if you need your organization verified.
</Warning>

## Authoring Flow

Creating a working integration takes three calls, in order. Each returns an id the next one needs.

<Steps>
  <Step title="Create a Provider">
    A provider is the vendor or system the integration talks to — Google, Slack, your own internal service. Create one with `POST /provider` and keep the returned `id`. Reuse it for every integration from the same vendor.
  </Step>

  <Step title="Create the Integration">
    `POST /` registers the integration under that provider, optionally with its actions inline. Keep the returned `versionId`.
  </Step>

  <Step title="Add a Credential">
    `POST /v/{integrationVersionId}/credential` defines how the integration authenticates — which fields exist and how they render. This is the credential **schema**, never the secret values.
  </Step>
</Steps>

<Note>
  Steps 2 and 3 can be collapsed into one call: pass a `credential` object inside the integration body and it is created alongside it.
</Note>

## Actions and Fields

An action is one thing an integration can do. It carries an `inputs` and an `outputs` map describing its data, plus the Python `code` that runs when the action executes.

Both maps are keyed by the field's own `variableName`:

```json theme={null}
{
  "query": {
    "id": "1",
    "variableName": "query",
    "displayName": "Query",
    "allowedTypes": [{ "type": "str" }]
  }
}
```

The key and the `variableName` inside it must match. Your `code` reads inputs from `input_data[...]` and writes outputs to `result[...]` using those same names.

For composite types, `allowedTypes[].typeDefinition` describes the shape inside — for `array` a single-key map naming the element, for `object` a map of its properties. Values nest, so a list of records is `array` → `object` → properties.

## Usage Notes

* **Nothing is workspace-scoped.** Providers, integrations and credentials all belong to your organization. No workspace id is accepted anywhere in this section.
* **One credential per auth type.** Adding a second credential with the same `authType` to the same integration returns `409`.
* **A failed action does not roll back the integration.** If an inline action is rejected, the integration itself may still have been created. Check before retrying, or you will end up with duplicates.
* **`400` is us, `422` is downstream.** A `400` means this API rejected your body. A `422` means it passed validation here and was rejected further down — most often an `email` on a reserved domain.

## Available Endpoints

<CardGroup cols={2}>
  <Card title="Create a Provider" icon="building" href="/api-reference/v1-integration/create-provider">
    Register the vendor or system an integration is authored under
  </Card>

  <Card title="Create an Integration" icon="puzzle-piece" href="/api-reference/v1-integration/create-integration">
    Register a custom integration, optionally with its actions and credential
  </Card>

  <Card title="Add a Credential" icon="key" href="/api-reference/v1-integration/create-credential">
    Define how an integration authenticates
  </Card>
</CardGroup>
