hermosodocs

Use Hermoso as your backend

If you build a product for your own customers, you can run publishing, scheduling, inboxes and creative on Hermoso through the REST API. Each of your customers gets a brand. They connect their own social accounts from a link you hand them, and they never need a Hermoso login.

What this page covers is available today. Our Terms of Service allow you to build on the API and offer it to your own customers. You are responsible for your customers following each platform's own terms, and our acceptable use rules apply to everything that runs through your key.

The flow, end to end

  1. Create a key in the app on the API, MCP & CLI tab, under Terminal & API keys, and send it as Authorization: Bearer hmk_... from your server. The API refuses browser calls on purpose.
  2. Register where your customers come back to. PUT /v1/connect-redirects with {"urls": ["https://app.yourproduct.com/hermoso"]}. https only (http://localhost is accepted while you test). A link can only send people back to an address under one of these.
  3. Create a brand per customer with POST /v1/tools/create_brand. GET /v1/brands lists the ids. Every call after this names the brand with the X-Hermoso-User header.
  4. Connect a webhook on the brand (optional, recommended): POST /v1/tools/connect_connector with {"provider": "webhook", "webhookUrl": "https://..."}. The signing secret comes back once. Then choose the events with set_alert_events (see Webhooks).
  5. Create a connect link for the platform your customer wants to connect:
    POST /v1/connect-links
    X-Hermoso-User: <brand id>
    {
      "provider": "tiktok",
      "redirect_url": "https://app.yourproduct.com/hermoso/done",
      "state": "your-customer-id",
      "expires_in_minutes": 60
    }
    The answer carries url. Show it to your customer as a button or open it in a new tab.
  6. Your customer connects. They see a short Hermoso page, accept Hermoso's Terms and Privacy Policy, sign in on the platform's own consent screen, and land back on your redirect_url.
  7. You find out it connected from the query string on your redirect, from the account.connected webhook, or by polling GET /v1/connect-links/{id}.
  8. Publish with POST /v1/posts on that brand, now or scheduled.

Providers

meta (Facebook Pages and the Instagram accounts linked to them), instagram (an Instagram account on its own login, no Facebook Page needed), tiktok, youtube, linkedin, linkedin_community (lets the brand comment as its LinkedIn Page), x, pinterest, threads, google_business, and the ad platforms. A provider that is not available yet is refused with the list. Accounts that connect with a pasted key, such as Bluesky and Telegram, are connected with POST /v1/tools/connect_connector instead.

What comes back on your redirect

Your own query string is kept. We add these, and a parameter of yours with the same name is overwritten:

ParameterValue
connect_statussuccess, cancelled or error
providerThe provider the link was for
brandThe brand id
link_idThe link's id
accountThe connected account's handle or name, on success
error_codeOn an error: access_denied, provider_error, connection_failed, different_browser, host_connection_missing
stateThe state you passed

Treat the redirect as a hint for your UI, not as proof: confirm with GET /v1/connect-links/{id} or the webhook before you rely on it.

Rules a link follows

Whose name is on the consent screen

The platform's consent screen shows Hermoso, because the connection is made through Hermoso's app on that platform. Our page tells your customer this before they reach it. Your customer can remove that access at any time in the platform's own settings.

Your customers and Hermoso

On the connect page your customer accepts Hermoso's Terms of Service and Privacy Policy, so they are also a Hermoso user under those terms.

Choosing Pages after a Facebook or LinkedIn connect

A Facebook login can reach many Pages, and a LinkedIn login reaches the person's profile and every Page they manage. Nothing is posted to until the brand has a choice saved. The link's creator owns that choice: call list_connector_accounts and then set_connector_accounts through POST /v1/tools/{name}. account_selection_required on the link (and in the account.connected event) tells you when this step applies.

Connections

Webhooks

A brand's webhook receives signed events (Standard Webhooks: webhook-id, webhook-timestamp, webhook-signature with v1,<base64 HMAC-SHA256 of "id.timestamp.body">). A delivery that fails with a 5xx, 408, 425, 429 or a timeout is tried up to seven times over about 16 hours, and every event carries a stable webhook-id so you can drop a duplicate. Choose groups with set_alert_events; rotate the secret with rotate_webhook_signing_secret; read the delivery log with list_alert_settings.

GroupEventsOn by default
connectionsaccount.connected, account.disconnectedYes
inboxcomment.received, message.receivedNo, name it to receive it
postspost.published, post.partial, post.failedYes
renders, approvals, watch, credits, leadsRenders, drafts awaiting approval, competitor finds, low credits, new leadsYes

Every payload names the brand. account.connected also carries provider, account, link_id, your state and account_selection_required.

Comments and DMs

comment.received and message.received come from what the platform pushes to us: Facebook Page comments, Messenger, Instagram comments and Instagram Direct. Each carries the platform, the ids you need to answer (comment_id or message_id), the text and the sender. A brand's own comments are not sent. For an Instagram account connected with the instagram provider this is on as soon as it connects. For a Facebook Page, call subscribe_meta_webhooks once with the fields feed and messages. Other platforms do not push comments or messages to us; read them with list_inbox.

First comment

Send first_comment on POST /v1/posts (or firstComment on schedule_post, post_to_meta and post_to_linkedin_page) and the account comments on its own post right after it publishes.

Limits

Rate limits are per API key and are sent on every response as X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Each platform's own posting limits still apply. Plans, prices and limits can change; the current ones are on the pricing page and in Credits & costs.