PM3K REST API — TikTok Posting Service

1. What this service does

PM3K gives you two main ways to work with TikTok:

Base URLs (production):

All responses are JSON with Content-Type: application/json; charset=UTF-8.

2. Authentication & plans

2.1. Sign in and plan

  1. Go to pm3k.org.
  2. Click Connect / Sign in with TikTok.
  3. Approve requested scopes in TikTok (official OAuth 2.0 + PKCE flow).
  4. Choose a plan: Free, Monthly, or Annual.

PM3K stores your TikTok open_id and plan in internal storage (KV).

Free plan basics:

Paid plans increase key lifetime, storage TTL and upload limits, but TikTok anti-spam limits stay the same.

2.2. API key

  1. In the dashboard, open the API key section.
  2. Click Issue / Regenerate key.
  3. Copy the key and store it in your tool (n8n, Make, etc.) as a secret.

Important:

Use this header for all API calls:

Authorization: Bearer YOUR_API_KEY_HERE

3. Video source (source_url)

You always pass a URL to the video file, not the file itself. Two common options:

3.1. PM3K storage (recommended for testing)

  1. In the dashboard, use the Upload section.
  2. PM3K stores your file in cloud sorage with a TTL based on your plan.
  3. You get an HTTPS URL like:
    https://files.pm3k.org/uploads/<open_id>/<date>/<id>.mp4
  4. You can use this URL as source_url in direct_post.

3.2. Your own hosting (CDN / object storage)

Available on all plans (Free / Monthly / Annual) after verification.

Requirements for your own domain:

File size limit: Free plan is typically around 100 MB, paid plans around 200 MB. Larger files may fail with tiktok_error or proxy_error.

Domain verification flow:

  1. In the dashboard, open the section for storage / domains.
  2. Click Add domain and enter your root domain (for example media.example.com).
  3. PM3K will generate a small .txt verification file that you need to upload to the root of your domain (for example: https://your-domain.com/pm3k-verify.txt).
  4. Just add the file on your side, then click Verify in the dashboard.
  5. Once the domain is marked as verified, you can safely use URLs from that domain as source_url in the API.

Even for a verified domain, PM3K will still pull your video through its own storage first (temporary copy) to build a fingerprint (size + ETag) and run duplicate / anti-spam checks. TikTok does not fetch directly from your domain via this API; PM3K sits in the middle for better safety and de-duplication.

4. Endpoint: POST /api/tiktok/direct_post

4.1. Purpose

Create a TikTok post using PULL_FROM_URL.

4.2. Request

URL

POST https://pm3k.org/api/tiktok/direct_post

Headers

Authorization: Bearer YOUR_API_KEY_HERE
Content-Type: application/json
Accept: application/json

Body (basic)

{
  "source_url": "https://files.pm3k.org/uploads/.../video.mp4",
  "title": "Your TikTok caption here"
}

2. Direct Post (POST /api/tiktok/direct_post)

Use this endpoint from n8n, Make, or your own scripts to send a prepared vertical video directly to TikTok. The same payload is used for scheduled posts via /api/jobs.

{
  "source_url": "https://files.pm3k.org/abc123.mp4",
  "title": "Your TikTok caption here",
  "privacy": "PUBLIC_TO_EVERYONE",

  "disable_comment": false,
  "disable_duet": false,
  "disable_stitch": false,

  "is_ad": false,
  "ad_your_brand": false,
  "ad_branded_content": false,
  "brand": ""
}

Required fields

Important: The video must be vertical (9:16). PM3K does not re-encode, rotate or compress your video — the exact file you provide is uploaded to TikTok as-is. Files that are not vertical may be rejected with a bad_request error.

Duration limits: TikTok may reject videos that exceed the maximum duration allowed for your account. PM3K does not override this limit — TikTok enforces it on upload.

PM3K does not compress, modify or re-encode your video. The file hosted at source_url is the file TikTok receives.

Interaction settings

Ad / branded content fields

These fields are optional but recommended if you use PM3K for commercial posts. They are designed to reflect TikTok’s ad / branded content policies.

You don’t need to send any technical metadata (file size, ETag, etc.). PM3K reads everything it needs from its own storage and uses internal checks to block duplicate uploads and spammy captions.

4.3. Full service guide: Photo Mode (slides)

Photo Mode lets you publish a TikTok photo carousel (slides) using the same /api/tiktok/direct_post endpoint. PM3K always sends PULL_FROM_URL to TikTok and uses PM3K storage URLs for final delivery.

Photo payload (direct post)

{
  "media_type": "PHOTO",
  "photo_images": [
    "https://files.pm3k.org/uploads/<open_id>/albums/<album_id>/a.jpg",
    "https://files.pm3k.org/uploads/<open_id>/albums/<album_id>/b.webp"
  ],
  "photo_cover_index": 0,
  "auto_add_music": true,
  "title": "Caption for a photo post",
  "privacy": "PUBLIC_TO_EVERYONE",
  "disable_comment": false,
  "disable_duet": false,
  "disable_stitch": false,
  "is_ad": false,
  "brand": ""
}

Photo payload (schedule via /api/jobs)

{
  "kind": "tiktok",
  "run_at": "2026-02-01T12:30:00.000Z",
  "media_type": "PHOTO",
  "photo_images": [
    "https://files.pm3k.org/uploads/<open_id>/albums/<album_id>/a.jpg",
    "https://files.pm3k.org/uploads/<open_id>/albums/<album_id>/b.webp"
  ],
  "photo_cover_index": 1,
  "auto_add_music": false,
  "title": "Scheduled photo post",
  "privacy": "SELF_ONLY",
  "disable_comment": false,
  "disable_duet": false,
  "disable_stitch": false
}

Upload-only (get link) + retention

In the dashboard, Photo mode shows a live JSON payload as uploads complete. If you click Upload only (get link), PM3K upgrades retention for the album.

POST https://pm3k.org/api/album/retain
{ "album_id": "..." }

Use the resulting JSON in n8n/Make with /api/tiktok/direct_post.

Photo limits & rules

Posting limits are unchanged: max 1 post/hour and 10 posts/day total across photo/video/text for API usage. Dashboard upload limits remain plan-based (photo albums count as 1 upload).

Photo errors (common)

ErrorMeaning
too_few_imagesMissing images or empty array.
too_many_imagesMore than 35 images.
cover_out_of_rangeInvalid cover index.
unsupported_image_typeOnly JPEG/WebP allowed.
image_too_largeImage exceeds 20 MB.
image_too_large_pxImage exceeds 1080px on one side.
content_length_requiredMissing Content-Length for external URLs.
domain_not_verifiedExternal domain not verified.

4.4. Successful response

{
  "ok": true,
  "publish_id": "7153xxxxxxxxxxxxxxxxxx"
}

You will use publish_id with /api/tiktok/status to check the publish state.

5. Endpoint: POST /api/tiktok/status

5.1. Purpose

Check current TikTok publish status for a post created by direct_post.

5.2. Request

URL

POST https://pm3k.org/api/tiktok/status

Headers

Authorization: Bearer YOUR_API_KEY_HERE
Content-Type: application/json
Accept: application/json

Body

{
  "publish_id": "7153xxxxxxxxxxxxxxxxxx"
}

5.3. Successful response

{
  "ok": true,
  "status": "PUBLISHING",
  "state": "pending",
  "fail_reason": null,
  "raw": {
    "...": "TikTok original response"
  }
}

Fields:

5.4. Status rate limits

For /status, PM3K applies a soft limit of 20 calls per minute per TikTok account.

PM3K also enforces a hard limit of 40 calls per hour per open_id. The first time you exceed this limit in a 1-hour window, status polling enters a cooldown until your next successful post.

If exceeded, you receive:

{
  "ok": false,
  "error": "rate_limit_status",
  "message": "Too many /status calls for this account, please slow down.",
  "retry_after": "2025-01-01T12:00:00.000Z"
}

HTTP status: 429.

Hourly cooldown response:

{
  "ok": false,
  "error": "status_cooldown",
  "message": "Cooldown until next post.",
  "cooldown": "until_next_post"
}

If you already unlocked by posting, but the same hour window is still capped:

{
  "ok": false,
  "error": "hourly_limit_status",
  "retry_after": "2025-01-01T13:00:00.000Z",
  "resetAt": "2025-01-01T13:00:00.000Z"
}

Recommended polling pattern:

6. Scheduling and instant posting in the dashboard

You can manage TikTok posts directly from the PM3K dashboard. No extra API endpoints are required for this.

  1. Upload your video to PM3K storage — dashboard uploads always go through PM3K’s own storage. Videos from your own verified domain are used only from API calls, not from the dashboard upload flow.
  2. Once uploaded, the video will appear in the dashboard as an available source.
  3. Open the TikTok scheduling block (the card with “Now / Schedule” options).
  4. Choose your video, set the caption, and optional flags (disable comments / duets / stitches).
  5. To post immediately, select the Now mode and confirm. PM3K will send the request to TikTok as soon as you click publish.
  6. To schedule for later, select the Schedule mode, pick date and time, and save. PM3K will trigger the post at that time automatically, no additional calls needed.
  7. Also, after the video is uploaded, the dashboard shows a direct PM3K file URL (your video in PM3K storage). You can copy this URL and use it as source_url in your own low-code workflows (for example, call /api/tiktok/direct_post from n8n or Make).

7. Anti-spam rules & Acceptable Use

7.1. Links in captions

Captions with links are blocked. If title contains http://, https:// or www., PM3K rejects the request:

{
  "ok": false,
  "error": "links_forbidden",
  "message": "Links are not allowed in TikTok captions for this service."
}

HTTP status: 400.

7.2. Forbidden words

PM3K maintains a forbidden-words list (STOP_WORDS) covering, for example:

If your caption contains one of these words or phrases, PM3K returns:

{
  "ok": false,
  "error": "forbidden_word",
  "message": "Caption contains forbidden content: \"...\"."
}

HTTP status: 400. Such captions are not sent to TikTok at all.

7.3. Duplicate video protection

PM3K avoids posting the same video repeatedly for the same account. A fingerprint is built from source_url, file size and ETag.

If the same fingerprint was used on this account in the last 12 months:

{
  "ok": false,
  "error": "video_duplicate",
  "message": "This video URL was already used for this TikTok account recently."
}

HTTP status: 400.

7.4. Duplicate captions

Two layers:

  1. Per account – if the same caption is used on the same account within 12 months:
    {
      "ok": false,
      "error": "caption_duplicate_account",
      "message": "This caption was already used on this TikTok account recently."
    }
  2. Global soft limit – if the same caption is used on more than 5 different accounts in 24 hours:
    {
      "ok": false,
      "error": "caption_global_spam",
      "message": "This caption is being reused across too many accounts in a short time."
    }

Both responses use HTTP status 400.

7.5. Posting limits

Per TikTok account (per creator_id):

If you exceed these limits:

{
  "ok": false,
  "error": "daily_limit",
  "message": "Daily TikTok posting limit (10/day) reached."
}

or

{
  "ok": false,
  "error": "interval_limit",
  "message": "You must wait about N more minutes before next TikTok post."
}

HTTP status: 429.

7.6. TikTok 429 & cooldown

If TikTok itself returns HTTP 429 (rate limit) for your account, PM3K sets a cooldown for this creator_id (around 3 hours).

During cooldown you will see:

{
  "ok": false,
  "error": "tiktok_rate_limit",
  "message": "TikTok returned HTTP 429 (rate limit) for this account; posting is temporarily paused.",
  "retry_after_seconds": 10800
}

or subsequent calls will return:

{
  "ok": false,
  "error": "tiktok_cooldown",
  "message": "TikTok recently returned HTTP 429 for this account; posting is temporarily paused."
}

Both use HTTP status 429. Do not auto-retry during cooldown.

8. Error reference (quick lookup)

Common error values in API responses:

9. Simple n8n pattern

9.1. Node 1 — HTTP Request: create TikTok post

Body (JSON):

{
  "source_url": "https://files.pm3k.org/uploads/.../video.mp4",
  "title": "My caption without links"
}

Store ok and publish_id from the response. If ok is false, log error and message and stop the flow.

In n8n, always add an IF node right after this step: if ok == true → continue to the status loop; if ok == false → stop the flow and log error/message. Do not try to access publish_id when ok is false.

9.2. Node 2 — Loop with Wait + Status

  1. Wait 10–15 seconds.
  2. Call POST https://pm3k.org/api/tiktok/status with:
    {
      "publish_id": "{{$json["publish_id"]}}"
    }
  3. Check:
    • If state == "done" → success.
    • If state == "failed" → log fail_reason and stop.
    • Else (still pending) → wait and repeat, up to a max attempts limit.