---
title: "Add an OAuth app"
method: POST
path: "/v1/connect/oauth-apps"
tags: ["Connect"]
---

# Add an OAuth app

`POST /v1/connect/oauth-apps`

## Request

- Base URL: `https://zernio.com/api`
- URL: `https://zernio.com/api/v1/connect/oauth-apps`
- Auth: HTTP bearer

Saves your app's client ID and secret for a platform.

The keys are checked with the platform first:

- Keys it rejects return 400 OAUTH_APP_KEYS_REJECTED and are not saved.
- Keys it could not check are saved with status `unchecked`.

Allow the returned `redirectUri` in your app's settings on the platform before connecting.

Only the account owner or a full-access team member can add apps, and not with a profile-scoped API key.

## Request body

- object
  - `platform` string, required: One of the platforms listed in `platforms` of GET /v1/connect/oauth-apps.
  - `label` string, required
  - `clientId` string, required
  - `clientSecret` string, required
  - `metaAppId` string: Instagram only: the numeric ID of the Meta app your Instagram app lives in. Zernio uses it with `metaAppSecret` to register the webhook. Send both or neither.
  - `metaAppSecret` string: Instagram only: the secret of that Meta app. Never returned.
  - `slackSigningSecret` string: Slack only: the signing secret from the app's Basic Information page. Needed to receive events from your Slack app; any other platform is a 400.
  - `scopeAreas` string[]: Areas this app requests. Defaults to every area the platform supports; an area the platform cannot request separately is a 400.

## Response `201`

The app was saved.

- object
  - `app` OAuthApp, required
    - `id` string, required: Pass it as `oauthAppId` on GET /v1/connect/{platform} to connect through this app.
    - `platform` string, required: The platform the app belongs to, as in GET /v1/connect/{platform}.
    - `label` string, required
    - `clientId` string, required: The client ID (or app ID) of your app on the platform. The secret is never returned.
    - `scopeAreas` string[], required: The permission areas every connect through this app requests. Pick only what your app is approved for on the platform.
    - `status` 'ok' | 'unchecked' | 'invalid', required: `ok`: the platform accepted the keys at the last check. `unchecked`: the check could not reach a verdict (see lastError). `invalid`: the platform rejected the keys; connects and token refreshes through this app will fail until the secret is rotated.
    - `lastCheckedAt` string, date-time, nullable
    - `lastError` string, nullable
    - `accountCount` integer, required: Connected accounts currently running on this app.
    - `redirectUri` string, uri, required: The OAuth redirect URI to allow in your app's settings on the platform.
    - `webhook` object, nullable: Facebook and Instagram only; null on platforms with nothing to set up. Meta delivers comments and messages to your app's own webhook. Set this callback URL and verify token on the app's webhook product (Page for Facebook, Instagram for Instagram) and subscribe the listed fields. Zernio checks each delivery against your app secret.
      - `callbackUrl` string, uri, required
      - `verifyToken` string, required
      - `object` 'page' | 'instagram', required: The webhook object to configure.
      - `fields` string[], required: Subscribe the app to these fields.
    - `sharedWebhookUrl` string, uri, nullable: TikTok only: set this as the webhook callback URL in your TikTok developer app. TikTok uses it to report when a video finishes publishing; Zernio also checks the publish status itself, so posting works without it. Null on other platforms.
    - `hasSlackSigningSecret` boolean: Slack only: whether the signing secret of your Slack app is saved. Without it Zernio refuses every event sent to `slackEvents.requestUrl`.
    - `slackEvents` object, nullable: Slack only; null on other platforms. Slack delivers messages and mentions to your app's own Request URL. Save the app's signing secret first (`slackSigningSecret`), then set this Request URL under Event Subscriptions and subscribe the listed bot events. Zernio checks each delivery against that secret.
      - `requestUrl` string, uri, required
      - `botEvents` string[], required: Subscribe the app to these bot events.
    - `createdAt` string, date-time, required

## Other responses

- `400`: Invalid request
- `401`: Missing or invalid API key. `code` is `missing_credentials` when no Authorization header was sent and `invalid_credentials` when the key is unknown, revoked or expired.
- `403`: The caller cannot change workspace settings (INSUFFICIENT_PERMISSIONS).
- `409`: The workspace already has an app with this client ID on this platform (OAUTH_APP_ALREADY_EXISTS); `details.appId` names it. Rotate its secret with PATCH instead.

## Changes

- **2026-10-30** `62ae2e766614`: 2 info
  - added the new optional request property `metaAppId`
  - added the new optional request property `metaAppSecret`
- **2026-10-29** `134756fb8dc2`: 3 info
  - added the new optional request property `slackSigningSecret`
  - added the optional property `app/hasSlackSigningSecret` to the response with the `201` status
  - added the optional property `app/slackEvents` to the response with the `201` status
- **2026-10-29** `1b0c783e7f44`: 1 info
  - added the optional property `app/sharedWebhookUrl` to the response with the `201` status
- **2026-10-28** `0ef14b964717`: 1 breaking, 2 info
  - removed the enum value `ads` of the request property `scopeAreas/items/`
  - added the optional property `app/webhook` to the response with the `201` status
  - removed the `ads` enum value from the `app/scopeAreas/items/` response property for the response status `201`
- **2026-10-28** `9f1c5346e670`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/zernio/apis/zernio-api/changes/v1/connect/oauth-apps/post.md)

---

[API](https://skmtc.dev/zernio/apis/zernio-api.md) - [All operations](https://skmtc.dev/zernio/apis/zernio-api/llms.txt) - [OpenAPI document](https://skmtc.dev/zernio/apis/zernio-api/revisions/c319eb5d95b6?raw)
