Posts

Bulk upload from CSV

Changed on

Create multiple posts by uploading a CSV file. Use dryRun=true to validate without creating posts.

CSV columns:

  • Required: platforms, profiles, and a schedule (one of schedule_time, a schedule_time_<platform> override, publish_now=true, use_queue=true, or is_draft=true).
  • Content: at least one of post_content, title, or media_urls is required.
  • Aliases: a handful of columns accept the JSON field name from POST /v1/posts, since integrators infer the CSV shape from that endpoint's body. When both are present the real CSV column wins, unless it is blank for that row, in which case the alias value is used.
    • content aliases post_content
    • timezone aliases tz
    • scheduledFor aliases schedule_time
    • mediaUrls aliases media_urls
  • Per-platform overrides use three dynamic column prefixes, one column per platform (e.g. schedule_time_instagram, custom_content_tiktok, custom_media_youtube): schedule_time_<platform>, custom_content_<platform>, custom_media_<platform>.
  • Any other column is not read. It does not error, but it is reported in the response's warnings array as unknown_columns:<a,b,c> (see BulkUploadResult), so a misnamed or unsupported column is never silently dropped.
  • Timezone: tz sets the zone schedule_time is read in. A row without tz uses its profile's timezone (when all its target profiles share one), else UTC.
  • Row limits: 5000 rows is a hard cap that returns 400 above it. 500 rows is only an advisory threshold, it adds rows_exceed_advisory_limit:500 to warnings and the request still processes.

Example row (header + one data row):

post_content,platforms,profiles,schedule_time,tz
"Hello world",instagram,MyProfile,2026-09-01 10:00,America/New_York
post/v1/posts/bulk-upload

Request

  • Base URL: https://zernio.com/api
  • URL: https://zernio.com/api/v1/posts/bulk-upload
  • Auth: HTTP bearer

Query parameters

dryRunboolean

Response

Bulk upload results. Returned when every row succeeded (or every row failed). A mix of successes and failures returns 207 instead, with the same body shape.

totalinteger

Number of data rows processed from the CSV

validinteger

Count of rows that succeeded (results[].ok === true)

invalidinteger

Count of rows that failed (total - valid)

warningsstring[]

Top-level advisory warnings, e.g. rows_exceed_advisory_limit:500 or unknown_columns:<a,b,c> (comma-separated unrecognized CSV column names). Empty when none.

Changes

    • warning

      added the new account enum value to the / response property for the response status

    • warning

      added the new account enum value to the / response property for the response status

    • warning

      added the new account enum value to the / response property for the response status

    • info

      added the optional property to the response with the status

    • info

      added the optional property to the response with the status

    • info

      added the optional property to the response with the status

    • info

      added the optional property to the response with the status

    • info

      added the optional property to the response with the status

    • info

      added the optional property to the response with the status

    • info

      added the optional property to the response with the status

    • info

      added the optional property to the response with the status

    • info

      added the optional property to the response with the status