Integration recipe
Publish a post with curl and the pixPLace API
Upload an image by URL and publish a post with two curl commands. Bearer key, Idempotency-Key, retries and the common errors explained.
Who it is for
Anyone who wants to try the API in a terminal first, or call it from a shell script or a cron job.
What it automates
Publish a post with an image: the server downloads the image from a public URL, then the post is created with the stored copy.
Steps
- Create an API key in Settings → Developer and export it as PIXPLACE_API_KEY. The full key is shown once.
- Call POST /api/v1/uploads/from-url with the public image URL. The answer holds data.publicUrl.
- Call POST /api/v1/posts with data.publicUrl as attachments[].url and its type as attachments[].type.
- Send an Idempotency-Key on both calls. If a call times out, repeat it with the same key: you get the original result, never a duplicate.
- When you create the key, tick the `publish` scope. A key without it gets 403 insufficient_scope on these calls.
Examples
Placeholders: ppk_live_XXXXXXXX is your key. The ids and the image address are samples. The API address is always https://pixplace.space/api/v1.
Step 1: upload the image by URL
curl -X POST https://pixplace.space/api/v1/uploads/from-url \
-H "Authorization: Bearer ppk_live_XXXXXXXX" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: upload-0001" \
-d '{
"url": "https://example.com/photos/living-room.jpg"
}'Step 2: create the post with data.publicUrl
curl -X POST https://pixplace.space/api/v1/posts \
-H "Authorization: Bearer ppk_live_XXXXXXXX" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: post-0001" \
-d '{
"title": "Minimalist living room",
"attachments": [
{
"url": "https://cdn.pixplace.space/content/cm00000000000000000000001/2026-10/00000000-0000-4000-8000-000000000004.jpg",
"type": "IMAGE"
}
],
"description": "AI-generated interior concept"
}'Read the answer with jq
# the post address is in data.url of the step 2 answer
curl -s -X POST ... | jq -r .data.urlCommon errors
| Status | Cause | What to do |
|---|---|---|
| 400 | The body is invalid: a missing title, a media URL that is not https, or a type other than IMAGE or VIDEO. The message names the field. | Fix the field named in the error message. Nothing was written and no quota was spent, so do not retry the same body. |
| 401 | The API key is missing, malformed, revoked or sent in the wrong header. | In curl the key goes into -H "Authorization: Bearer ...", not into the URL. The header must read Authorization: Bearer followed by your ppk_live_ key. Check the key in Settings → Developer. |
| 403 | The key lacks a scope the call needs: the answer is 403 with error.code insufficient_scope and the missing scope in error.required. | Create a new key in Settings → Developer with the `publish` scope ticked and use it instead; repeating the call with the same key fails the same way. |
| 429 | A per-minute or per-day limit was reached. The Retry-After header and the retryAfter field of the body say how many seconds to wait. | Wait that long and repeat with the SAME Idempotency-Key. In a script, read the Retry-After header with curl -i and sleep that many seconds. |
| 502 | The server could not download the source URL: it answered 4xx or 5xx, the host does not resolve or the response was compressed. | Open the source URL in a private browser window. It must be public and answer 200 without a login. |
The full list of statuses, the retry rules and the limits are in Errors and retries.