DEVELOPER DOCUMENTATION
Publish Job
Publish a draft job to the marketplace.
/api/public/v1/jobs/{id}/publishTakes a publishReady draft live on the marketplace. The final step of the posting loop: create → gap-fill → publish. Idempotent — publishing an already-open job returns 200 with alreadyPublished: true.
Every publish passes content moderation, and accounts have a daily publish limit (20/day claimed, 3/day unclaimed). A draft that is not publish-ready is rejected with the same validation detail the draft endpoints return — go back and patch the missing fields.
Requirements: jobs:write scope + the public_api_job_publishing feature (check capabilities → capabilities.publish). Works pre-claim within the lower daily limit.
Request
Section titled “Request”idstringpathrequiredThe draft job ID.
No body.
Response
Section titled “Response”okbooleantrue on success.
jobIdstringThe job ID.
statusstringOPEN — the job is live.
alreadyPublishedbooleantrue when the job was already open (no-op).
jobUrlstringPublic listing URL.
publishAttemptIdstring | nullInternal attempt identifier for support/audit, when available.
warningsstring[]Non-blocking warnings (e.g. fields worth improving).
sideEffectsobject{dispatched, status} — whether post-publish side effects (distribution, notifications) were kicked off.
Errors
Section titled “Errors”| Status | code | Meaning |
|---|---|---|
400 | BAD_REQUEST | Draft is not publish-ready — details.validation carries the same missingFields/issues shape as the draft endpoints |
401 | UNAUTHORIZED | Missing or invalid token |
403 | FORBIDDEN | Missing scope, feature disabled, or moderation block (details.reason: "moderation_blocked" with details.reasons[]) |
404 | NOT_FOUND | No such job, or not yours |
429 | RATE_LIMITED | Daily publish limit reached — details carries {limit, windowHours: 24} |