HoplaDocs

Images

Upload an image to Hopla and use it as a profile photo, thumbnail, gallery item or page background.

Pages only display images hosted by Hopla: fast loading, no third-party dependency, no visitor tracking. Uploading is a two-step process: POST /media stores the image and returns its path, then that path is used in settings or in a block.

Upload

Supported formats: WebP, JPEG or PNG, 1.5 MB maximum. Two upload methods:

The request body contains the binary image, with its MIME type in Content-Type.

curl -X POST https://app.hopla.page/api/v2/media \
  -H "Authorization: Bearer $HOPLA_API_KEY" \
  -H "Content-Type: image/jpeg" \
  --data-binary @portrait.jpg
201 Created
{
  "media": {
    "path": "/media/054a3c6991bc.png",
    "url": "https://hopla.page/media/054a3c6991bc.png"
  }
}

The format is detected from the file signature (magic bytes), not from its extension: a GIF renamed to .png returns 415.

Usage

LocationField
Profile photoPATCH /settings with {"profile": {"avatar": "/media/…"}}
Page background (Starter)PATCH /settings with {"backgroundImage": "/media/…"}
Link thumbnail, product photoBlock image
Galleryimages of a gallery block, a list of paths
Update the profile photo with Node.js
import { readFile } from 'node:fs/promises';

const key = process.env.HOPLA_API_KEY;
const api = 'https://app.hopla.page/api/v2';

const upload = await fetch(`${api}/media`, {
  method: 'POST',
  headers: { Authorization: `Bearer ${key}`, 'Content-Type': 'image/jpeg' },
  body: await readFile('portrait.jpg'),
});
const { media } = await upload.json();

await fetch(`${api}/settings`, {
  method: 'PATCH',
  headers: { Authorization: `Bearer ${key}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ profile: { avatar: media.path } }),
});

Errors

StatuscodeCause
400missing_imageEmpty body, or image is not a data URL
413image_too_largeImage over 1.5 MB
413storage_quota_exceededImage storage quota exceeded: delete images in the admin panel
415unsupported_image_formatFormat other than WebP, JPEG or PNG
403read_only_keyThe key is read-only

On this page