Zernio

Schedule and publish social media posts from Convex with durable workpool submission, per-post reactive status, and signed webhook updates for Instagram, TikTok

Installation

npm install @zernio/convex

Benefits

Use cases

how to schedule social media posts from a Convex backend

The @zernio/convex component exposes a schedulePost method you call inside a Convex mutation. It writes a row immediately and submits the post to the Zernio API through a durable workpool with up to five retries on network and server errors. You can supply a scheduledFor timestamp in milliseconds or omit it to publish immediately.

how to get webhook updates for social media post status in Convex

Zernio sends signed webhook events for post.scheduled, post.published, post.failed, post.partial, post.cancelled, and per-platform variants. The @zernio/convex component mounts a POST handler at /zernio/webhook via registerRoutes, verifies the HMAC signature against ZERNIO_WEBHOOK_SECRET, and writes the updated status into its own Convex table. You can then expose that status as a reactive query with zernio.status(ctx, postId).

how to connect Instagram or TikTok accounts to a Convex app with OAuth

The @zernio/convex component provides connectAccountUrl to generate a Zernio OAuth URL for a given platform such as instagram or tiktok, and syncAccounts to pull connected accounts into a local Convex table. After OAuth completes, calling zernio.listAccounts returns rows with zernioAccountId values that you pass directly to schedulePost.

how to deduplicate social media post submissions in Convex

schedulePost in @zernio/convex derives an idempotency key from the profile, accounts, content, media, and schedule when you do not supply one, so retrying a mutation does not publish twice. You can also pass an explicit idempotencyKey such as a job id or invoice id to guarantee exactly one post for the lifetime of that key. The key is scoped to the Zernio profile so tenants cannot collide.

Frequently asked questions

Does @zernio/convex publish posts immediately when schedulePost is called?

No. By default testMode is true, which means every post is created in Zernio as a draft. Nothing is published until you explicitly set testMode to false in the Zernio constructor options. The schedulePost call itself returns as soon as the row is written to Convex; actual submission to the Zernio API happens asynchronously in a durable workpool.

What environment variables does the @zernio/convex component require?

The component reads four variables from process.env on every call: ZERNIO_API_KEY for bearer auth, ZERNIO_WEBHOOK_SECRET for HMAC verification of incoming webhooks, ZERNIO_PROFILE_ID for single-tenant mode, and ZERNIO_BASE_URL to override the API host. Only ZERNIO_API_KEY and ZERNIO_WEBHOOK_SECRET are required for all apps; ZERNIO_PROFILE_ID is only needed in single-tenant deployments.

How does @zernio/convex handle multi-tenant apps where each user has their own social accounts?

Supply a getUserInfo function to the Zernio constructor that returns a userId and optional email from ctx.auth. The component maintains a table mapping each userId to a Zernio profile id and creates the profile on the first connectAccountUrl or syncAccounts call using an idempotency key, so a retry never creates a duplicate profile. Idempotency keys and account rows are scoped per profile so tenants are isolated.

What retry behavior does @zernio/convex use when Zernio's API is temporarily unavailable?

The component submits posts through a workpool that attempts up to five deliveries on 408, 429, 5xx, and network errors, backing off at 1, 4, 16, and 64 minutes. This covers Zernio's escalating account cooldown windows of 10, 20, 40, and 80 minutes. Permanent 4xx errors are not retried and mark the post as failed. Before any retry re-submits, the component queries GET /v1/posts to adopt a post a previous attempt may have already created.

Which Zernio API key permissions are needed for the @zernio/convex component?

The component requires the publishing resource group for schedulePost and cancelPost, and the accounts resource group for syncAccounts and connectAccountUrl. The webhooks resource group is only needed if you manage webhook subscriptions programmatically via the request escape hatch rather than through the Zernio dashboard. A legacy full-access Zernio key already includes all three groups.

Links