Getting started
QuickstartConceptsRecommended setupsAuthenticationAPIs
Delivery APIOutbound webhooksLogsIngest webhookImagesErrorsLibraries
TypeScript SDKReference
Plans and limitsImages
Images sent with an article are copied to Copper CMS and served from the CDN.
Cover image
The cover is sent beside the article, as a url. Map coverImage.url to the field the partner sends it in, on the source page.
POST https://api.coppercms.com/v1/hook/8f2c…c1a9.k3Rd… content-type: application/json { "id": "post-1041", "title": "A post from the partner", "body": "<p>The body.</p><img src=\"https://img.partner.example/chart.png\" alt=\"Q3\">", "image": { "url": "https://img.partner.example/hero.jpg", "alt": "The harbour" } }
Other fields can sit beside the url, such as coverImage.alt. They are kept as sent.
Images in the body
Nothing needs mapping. Every image in the body is copied: an <img> in HTML,  in Markdown, an image node in TipTap JSON. The alt text and the title stay on the image.
What arrives
Each image is fetched when the article arrives, before the response. It is decoded and encoded again, which applies the rotation a phone camera records and drops the rest of the metadata, location included. An image with transparency is stored as PNG and every other image as JPEG.
The article then names the copy. The cover carries its size, so a page can lay it out before the image loads.
"coverImage": { "url": "https://cdn.coppercms.com/images/8f2c…c1a9/3b1e….jpg", "alt": "The harbour", "width": 1600, "height": 900 }
In bodyHtml, each src points at cdn.coppercms.com in the same way.
Sending an article again
An image is copied once per url. Sending the article again, or another article with the same image, reuses the copy and stores nothing new.
A changed image needs a new url. A file replaced at the same url keeps the copy that was made first.
A url already on cdn.coppercms.com is left as it is.
When an image cannot be copied
The article is refused, and nothing of it is written. The response names the image and the reason.
400 Bad Request { "error": "image could not be stored: https://img.partner.example/chart.png: the host answered 404" }
| Case | Answer |
|---|---|
| The host does not answer in time | 400 |
| The host answers with an error | 400 |
| The file is not an image | 400 |
| The file is too large | 400 |
| A private or local address | 400 |
| A relative url | 400 |
| Too many images | 400 |
| The account storage is full | 402 |
Fix the image and send the article again. The images copied before the failure are kept, so the next send fetches only the rest.
A refused article is kept for the source page, like any other refusal. A payload refused before the images, for a missing title or a site it cannot reach, fetches nothing.
Limits
| Largest image | 10 MB |
|---|---|
| Images copied per send | 50 |
| Time per image | 10 seconds |
| Time per send | 30 seconds |
| Redirects followed | 3 |
| Longest url | 2,048 characters |
An article past a limit is refused. Copies count toward storage, the same as uploads in the console. See Plans and limits.
