View all documentations

Typefully

When a Typefully draft is published, Wizard can post the published links into a configured Telegram chat.

Webhook signing uses one secret per Typefully social set. Those secrets live only in encrypted env JSON (plus a separate encryption key env).

[!IMPORTANT] Message sending only works if the Telegram account for telegramUserId is connected by the service at SALES_BACKEND_URL.

Server env vars

Variable Sensitive Purpose
TYPEFULLY_WEBHOOK_CONFIG_ENCRYPTED No (ciphertext only) Encrypted form of the secrets JSON object { "12345": "wh_sec_...", … }. Paste the encrypted field from the admin API after each change.
TYPEFULLY_WEBHOOK_CONFIG_KEY Yes Plain text in env; must be exactly 32 bytes for AES-256. Used only with TYPEFULLY_WEBHOOK_CONFIG_ENCRYPTED.
EXTENSION_SECRET_KEY Yes Authorization: Bearer <token> for the admin API below (same token pattern as other internal /api routes).
SALES_BACKEND_URL Base URL for the sales backend (Telegram send).

Generating a key

Example (32 characters, e.g. hex from random bytes):

openssl rand -hex 16

Admin API (mutate config, then paste into Vercel)

Base path: /api/typefully-config

All methods require:

Authorization: Bearer <EXTENSION_SECRET_KEY>

GET

Returns the configured social sets as an object: keys are decimal social set ids, values are truncated secret previews (never full webhook secrets).

Example response:

{
  "secrets": {
    "12345": "wh_sec_abcde..."
  }
}

If TYPEFULLY_WEBHOOK_CONFIG_KEY is missing, the server responds with 503. If the encrypted value cannot be decrypted (wrong key or corrupt blob), the server responds with 500.

POST — append social set(s)

Body is a non-empty array of { "socialSetId", "webhookSecret" } (same ids as in the stored map, as numbers):

[{ "socialSetId": 12345, "webhookSecret": "<typefully webhook secret>" }]

Duplicate socialSetId in the body or an id that already exists in config → 409.

Response includes the new encrypted string (replace the entire TYPEFULLY_WEBHOOK_CONFIG_ENCRYPTED value in Vercel):

{
  "encrypted": "<base64>"
}

Bootstrap: leave TYPEFULLY_WEBHOOK_CONFIG_ENCRYPTED empty, set TYPEFULLY_WEBHOOK_CONFIG_KEY, then call POST once to obtain the first encrypted blob.

DELETE — remove one social set

Either:

  • DELETE /api/typefully-config?socialSetId=12345, or
  • DELETE with JSON body { "socialSetId": 12345 }

Unknown id → 404. Response shape matches POST (new encrypted value for Vercel).

After each mutation

  1. Copy encrypted from the JSON response into TYPEFULLY_WEBHOOK_CONFIG_ENCRYPTED in Vercel (or your host).
  2. Redeploy or wait for the platform to reload env, as required.

Map Telegram user → destination chat

Edit apps/webhooks/config/typefully.json:

  • Key: telegramUserId (string)
  • Value: chatId (string)

Only telegramUserIds present in this file are allowed to use the inbound webhook.

Add the webhook in Typefully

  • URL: https://<your-wizard-domain>/api/webhooks/typefully?telegramUserId=<telegramUserId>
  • Method: POST
  • Headers: Typefully sends X-Typefully-Timestamp and X-Typefully-Signature. Wizard parses the body, resolves the secret for data.social_set_id, then verifies the signature with that secret.

Behavior

  • Only the draft.published event is processed.
  • Only LinkedIn and X links are included in the Telegram message.
  • If encrypted config is missing, invalid, or contains no entries, the inbound webhook responds with 500.