# Test your OmniSocials API integration safely

> Index of all OmniSocials docs pages: https://docs.omnisocials.com/llms.txt

OmniSocials has no sandbox and no test mode. Every API key starts with `omsk_live_` and works on the real social accounts connected to its workspace. Testing safely comes down to controlling what can publish, and where.

:::caution
A request with `publish_now: true`, `POST /posts/create-and-publish`, `POST /posts/:id/publish`, or a `schedule_at` that you leave in place goes live on real accounts. Treat a test key like a production key.
:::

## Use a test workspace

Every API key belongs to one workspace. You pick it in the **Workspace** field when you create the key under **Settings → API**, and the key only sees that workspace's accounts, posts and media.

1. Create a workspace for testing in the dashboard and connect test accounts to it.
2. Create a key for that workspace, with only the scopes your tests need.
3. Check the target before a test run: `GET /accounts` returns `workspace_id` and `workspace_name`.

A workspace is part of your subscription, see [Billing](https://docs.omnisocials.com/billing.md#how-the-subscription-is-structured). A trial has full API access. When a trial or subscription lapses, requests fail with `402 subscription_inactive` until it is reactivated.

Webhooks you create with a key only receive events for that key's workspace, so test deliveries stay apart from production ones.

## Post to accounts you can test on

Connect social accounts that exist for testing, not your brand's main accounts. A few channels can keep a test post out of public view:

| Channel | How to keep a test post private |
|---------|----------------------------------|
| `tiktok` | `tiktok.privacy_level: "SELF_ONLY"` |
| `youtube` | `youtube.privacy_status: "private"` or `"unlisted"` |
| `pinterest` | Pin to a secret board. The `boards` array of `GET /accounts/:id` includes secret boards |
| `telegram` | Connect a channel or group that only your team is in |

The other channels have no visibility option in the API, so a test post there is public on that account. Mastodon posts are always public, and Threads accounts must be public profiles to connect.

## Start with drafts

Every post is a draft unless the request has `publish_now` or `schedule_at`. A draft never publishes on its own, so you can create, read, update and delete drafts as often as you like:

```bash
curl -X POST https://api.omnisocials.com/v1/posts/create \
  -H "Authorization: Bearer $OMNISOCIALS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": { "default": "Integration test" },
    "accounts": ["your-account-id"],
    "source": "integration-test"
  }'
```

A [planned draft](https://docs.omnisocials.com/creating-posts.md#planned-drafts) (`draft: true` with `schedule_at`) keeps its time on the dashboard calendar and still never publishes.

:::tip
Drafts skip most per-platform checks: character limits, media rules, Pinterest carousel ratios and the X credits check run when a post is scheduled or published. To run those checks without publishing, schedule the post well in the future, read the response, then delete it with `DELETE /posts/:id`, which cancels the scheduled publish. A `400` names the problem, and `warnings` reports X credits and image fit.
:::

Scheduling has side effects of its own: it fires `post.scheduled` to your webhooks, and a scheduled X post with a link reserves its credits until it publishes. To check a file on its own, use `POST /media/check` (see [Media](https://docs.omnisocials.com/media.md#check-compatibility-before-posting)).

For a human safety net, attach an [approval workflow](https://docs.omnisocials.com/creating-posts.md#approval-workflows): the post waits as `in_approval` and publishes only after the last step approves it.

## Clean up test posts

- `DELETE /posts/:id` removes a post from OmniSocials. On a scheduled post it cancels the publish.
- It never deletes a live post on a platform. To take one down, use "Delete from [platform]" on the post in the dashboard (every platform except Instagram and TikTok, whose APIs have no delete) or delete it in the platform's app. Telegram allows removal only in the first 48 hours.
- Label test posts with `source` (a free-form string, returned on every post) so a cleanup script can find them. `GET /posts` has no `source` filter, so filter the list on your side.

## Test webhooks

Webhook URLs must use HTTPS and resolve to a public host; private and loopback addresses are refused with `validation_error`. Two ways to receive test deliveries:

- **A request bin.** Register the URL of a request inspection service as a webhook. It shows each delivery's raw body and headers (`X-OmniSocials-Signature`, `X-OmniSocials-Delivery` and the rest), which is what you need to check your signature code.
- **A tunnel to your machine.** Expose your dev server with `cloudflared tunnel` or `ngrok http 3000` and register the tunnel URL.

There is no endpoint that sends a test event. Trigger real events without publishing anything:

| Event | How to trigger it in a test |
|-------|-----------------------------|
| `post.scheduled` | Create a post with `schedule_at` in the future through the API, then delete it |
| `post.approved`, `post.rejected` | Create a post with `approval_workflow_id` and a future `schedule_at`, approve or reject it, then delete it. An approved post publishes at its time |
| `post.published`, `post.failed` | These need a real publish. Use a private test post from the table above |

After a run, `GET /webhooks/:id` shows `failure_count` and `last_failure` for deliveries your endpoint did not accept. See [Webhooks](https://docs.omnisocials.com/webhooks.md) for the payloads and signature verification.

## Mind the limits

- The rate limit is 100 requests per minute per key. Give tests their own key, so a test run never uses up the production key's budget. See [Rate limits and errors](https://docs.omnisocials.com/rate-limits-and-errors.md).
- Each workspace can send 1,000 inbox replies per 24 hours, and every reply goes to a real person.
- X posts with a link cost 20 credits each, in tests too. Test X with link-free text unless the link is what you are testing.
- YouTube's daily API quota is shared by every OmniSocials customer. Keep YouTube test uploads few.

## Postman and OpenAPI

- **Postman collection:** import [omnisocials.postman_collection.json](https://docs.omnisocials.com/omnisocials.postman_collection.json) into Postman and add your API key as the Bearer token.
- **OpenAPI file:** [openapi.json](https://docs.omnisocials.com/openapi.json) describes every endpoint. Use it to generate a client, import it into another API tool, or validate responses in contract tests.

The [CLI](https://docs.omnisocials.com/cli.md) is handy for scripted checks too: every command takes `--json`.
