Skip to content

Quickstart

You need a partner API key. MissLess issues one when your partner account is set up. It starts with mls_live_ and is shown once. Export it:

Terminal window
export MISSLESS_API_KEY="mls_live_3f9ac2e8b71d4c5f9e2a7b6c1d0e"

Every call below goes to https://social.missless.tel/v1, sends Authorization: Bearer $MISSLESS_API_KEY, and uses JSON.

One workspace per customer. Pass your own user id as external_id so you can find it again.

Terminal window
curl -X POST https://social.missless.tel/v1/workspaces \
-H "Authorization: Bearer $MISSLESS_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "external_id": "user_123", "name": "Salon Nova", "timezone": "Europe/Amsterdam" }'

Response 201:

{
"id": "ws7k2m9p4q1r8t3",
"external_id": "user_123",
"name": "Salon Nova",
"timezone": "Europe/Amsterdam",
"settings": {},
"status": "active",
"accounts_count": 0,
"created": "2026-08-25T09:12:04Z",
"updated": "2026-08-25T09:12:04Z"
}

Calling this again with the same external_id returns 200 and the existing workspace. It is safe to run on every login.

Section titled “2. Create a connect link and send the user through it”
Terminal window
curl -X POST https://social.missless.tel/v1/workspaces/ws7k2m9p4q1r8t3/connect-links \
-H "Authorization: Bearer $MISSLESS_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "networks": ["facebook", "instagram"], "redirect_url": "https://app.example.com/settings/social" }'

Response 201:

{
"token": "ct7f3a9c1e5b2d8f4a6c0e",
"url": "https://social.missless.tel/connect/ct7f3a9c1e5b2d8f4a6c0e",
"expires_at": "2026-08-25T10:12:04Z"
}

Redirect the user to url. They click Continue with Facebook, approve the Meta consent, and land back on the connect page with their Pages and Instagram accounts listed. Because redirect_url was given, a Back to button returns them to you with ?connected=<n> appended. Each connected account fires an account.connected webhook.

Then list what they connected:

Terminal window
curl https://social.missless.tel/v1/workspaces/ws7k2m9p4q1r8t3/accounts \
-H "Authorization: Bearer $MISSLESS_API_KEY"
{
"data": [
{
"id": "acig4h2k5m7p9r1",
"workspace": "ws7k2m9p4q1r8t3",
"network": "instagram",
"platform_id": "17841400000000001",
"username": "salonnova",
"display_name": "Salon Nova",
"avatar_url": "https://scontent.example/avatar.jpg",
"page_id": "100000000000001",
"status": "active",
"last_error": null,
"scopes": ["instagram_basic", "instagram_content_publish", "instagram_manage_comments", "instagram_manage_messages", "instagram_manage_insights"],
"token_expires_at": null,
"connected_at": "2026-08-25T09:15:41Z"
},
{
"id": "acfb8n2c4v6b1m3",
"workspace": "ws7k2m9p4q1r8t3",
"network": "facebook",
"platform_id": "100000000000001",
"username": "salonnova",
"display_name": "Salon Nova",
"avatar_url": "https://scontent.example/page.jpg",
"page_id": "100000000000001",
"status": "active",
"last_error": null,
"scopes": ["pages_show_list", "pages_manage_posts", "pages_read_engagement", "pages_messaging"],
"token_expires_at": null,
"connected_at": "2026-08-25T09:15:41Z"
}
],
"page": 1,
"limit": 50,
"total": 2
}

Instagram needs at least one media item. Pass a public URL and MissLess fetches it, or upload a file as multipart (see Media).

Terminal window
curl -X POST https://social.missless.tel/v1/media \
-H "Authorization: Bearer $MISSLESS_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "workspace": "ws7k2m9p4q1r8t3", "url": "https://cdn.example.com/cuts/friday.jpg", "alt": "Fresh haircut, side view" }'

Response 201:

{
"id": "med9x2c4v6b8n1m",
"workspace": "ws7k2m9p4q1r8t3",
"kind": "image",
"mime": "image/jpeg",
"size": 482113,
"width": 1080,
"height": 1350,
"alt": "Fresh haircut, side view",
"url": "https://social.missless.tel/v1/media/med9x2c4v6b8n1m/file?sig=9b1f2e8d&exp=1756717924",
"created": "2026-08-25T09:18:02Z"
}

Target both accounts. ?wait=true holds the request for up to 25 seconds and returns the final post, so you do not need webhooks for the first test.

Terminal window
curl -X POST "https://social.missless.tel/v1/posts?wait=true" \
-H "Authorization: Bearer $MISSLESS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"workspace": "ws7k2m9p4q1r8t3",
"caption": "Fresh cuts, Friday walk-ins welcome",
"media": ["med9x2c4v6b8n1m"],
"targets": ["acig4h2k5m7p9r1", "acfb8n2c4v6b1m3"],
"external_ref": "acme:post:1234"
}'

Response 201:

{
"id": "pst5g7j9l2n4q6s",
"workspace": "ws7k2m9p4q1r8t3",
"external_ref": "acme:post:1234",
"caption": "Fresh cuts, Friday walk-ins welcome",
"media": [{ "id": "med9x2c4v6b8n1m", "kind": "image", "mime": "image/jpeg", "width": 1080, "height": 1350 }],
"targets": [
{
"account": "acig4h2k5m7p9r1",
"network": "instagram",
"username": "salonnova",
"status": "published",
"platform_post_id": "17900000000000001",
"permalink": "https://www.instagram.com/p/C_abc123/",
"error": null,
"published_at": "2026-08-25T09:20:11Z"
},
{
"account": "acfb8n2c4v6b1m3",
"network": "facebook",
"username": "salonnova",
"status": "published",
"platform_post_id": "100000000000001_200000000000002",
"permalink": "https://www.facebook.com/100000000000001/posts/200000000000002",
"error": null,
"published_at": "2026-08-25T09:20:09Z"
}
],
"schedule_at": null,
"status": "published",
"published_at": "2026-08-25T09:20:11Z",
"attempts": 1,
"last_error": null,
"created_by": "api",
"created": "2026-08-25T09:19:58Z",
"updated": "2026-08-25T09:20:11Z"
}

Leave out ?wait=true and the response comes back at once with status: "publishing". The outcome then arrives as a webhook, or you poll GET /v1/posts/pst5g7j9l2n4q6s.

Register one endpoint per partner. Do this once; every workspace’s events go to it.

Terminal window
curl -X PUT https://social.missless.tel/v1/webhook \
-H "Authorization: Bearer $MISSLESS_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "https://app.example.com/webhooks/missless", "events": ["*"] }'
{
"url": "https://app.example.com/webhooks/missless",
"events": ["*"],
"secret": "7d0b7c8f5a1e4c2b9f6d3a8e1c4b7f0a9d2e5c8b1a4f7d0c"
}

Store secret. It is shown once. From now on every publish ends with a POST to your URL:

{
"id": "evt1a3c5e7g9i2k",
"type": "post.published",
"created_at": "2026-08-25T09:20:11Z",
"partner": "acme",
"workspace": "ws7k2m9p4q1r8t3",
"external_id": "user_123",
"data": {
"id": "pst5g7j9l2n4q6s",
"external_ref": "acme:post:1234",
"status": "published",
"targets": [
{ "account": "acig4h2k5m7p9r1", "network": "instagram", "status": "published", "permalink": "https://www.instagram.com/p/C_abc123/" },
{ "account": "acfb8n2c4v6b1m3", "network": "facebook", "status": "published", "permalink": "https://www.facebook.com/100000000000001/posts/200000000000002" }
]
}
}

The headers X-MissLess-Signature and X-MissLess-Timestamp let you verify it came from MissLess. See Verify signatures. Use X-MissLess-Delivery to de-duplicate retries.