FOR DEVELOPERS

Read, write and automate Galleries over the WordPress REST API

The free plugin registers 80+ routes in one namespace — fotogrids/v1. More than a dozen are public and need no key at all. The whole content API — Galleries, Albums, items, rendering, Lightbox, metadata, stats and templates — is in Free.

Quick start

One call, no key

More than a dozen routes answer without authentication — their permission_callback returns true. This is one of them, and it is the whole request.

BASH

terminal

BASH

				
					curl https://example.com/wp-json/fotogrids/v1/gallery/42
				
			

What comes back

Six top-level keys: id, title, description, meta, items and shortcode.

description is the post content, not the excerpt. meta carries layout (falls back to grid), columns (falls back to 3) and album_id, which is null when the Gallery sits in no Album.

shortcode hands you the exact string an editor would paste, so a script can drop a working embed into a post without composing one by hand.

Endpoints

The routes you will use first

Every path below is relative to /wp-json/fotogrids/v1/. The Auth column is the capability the route checks — Open means no authentication at all.

Method
Route
Returns
Auth

GET

/gallery/{id}

Gallery object, items and shortcode

Open

POST

/gallery/render

Rendered html, css, js and fonts

Open

POST

/gallery/{id}/unlock

HTML for a password-protected Gallery

Open

POST

/gallery/lightbox/slides

Slide payloads by offset and limit

Open

GET

/galleries

Gallery list — per_page, page, search

Open

GET

/galleries/{id}/items

Items for one Gallery — limit, offset

Open

GET

/album/{id}

Album and the Galleries inside it

Open

GET

/items

Item query — gallery, limit, offset

Open

GET

/lightbox/item/{id}

EXIF, credit, file info, tags, people

Open

POST

/stats/view

Records a view

Open

POST

/stats/share

Records a share, plus network

Open

GET

/view/{id}/settings

Resolved View Collection settings

Open

GET

/templates/preview

Template preview — raw HTML, not JSON

Open

Nothing is sent with these requests. A non-preview read of /gallery/{id} does record a view, so pass preview=true when a job polls it.
Method
Route
Returns
Auth

POST

/gallery/{id}/featured-item

Sets or clears the Gallery cover

edit_post

POST

/album/{id}/featured-gallery

Sets which Gallery fronts an Album

edit_post

POST

/admin/galleries/{id}/items

Adds attachments to a Gallery

edit_post

POST

/admin/galleries/{id}/albums

Assigns a Gallery to an Album

edit_post

DELETE

/admin/galleries/{id}/albums/{album_id}

Removes that assignment

edit_post

POST

/admin/albums/{id}/galleries

Adds Galleries to an Album

edit_post

DELETE

/admin/albums/{id}/galleries/{gallery_id}

Removes a Gallery from an Album

edit_post

POST

/admin/albums/{id}/galleries/reorder

Reorders Galleries in an Album

edit_post

The check runs against the object you named in the URL, not a global switch. An author who can edit their own Gallery can add items to it and set its cover, and cannot touch a Gallery someone else owns.
Method
Route
Returns
Auth
GET POST

/admin/general-settings

Global defaults

manage_fotogrids_settings

GET POST

/admin/sharing-settings

Share buttons and networks

manage_fotogrids_settings

GET POST

/admin/watermark-settings

Watermark config, status, regenerate

manage_fotogrids_settings

GET POST

/admin/seo-settings

Alt text, structured data, image SEO

manage_fotogrids_settings

GET POST

/admin/view-settings

Standalone View Page behaviour

manage_fotogrids_settings

GET POST

/admin/advanced-settings

Advanced options

manage_fotogrids_settings

GET POST

/admin/roles

Which roles hold which capability

manage_fotogrids_settings

GET

/admin/stats/overview

Headline totals

view_fotogrids_stats

GET

/admin/stats/views

Views over a window — days up to 365

view_fotogrids_stats

GET

/admin/stats/popular-galleries

Ranked Galleries

view_fotogrids_stats

GET

/admin/stats/recent-activity

The recent event feed

view_fotogrids_stats

GET

/admin/stats/top-content

Top items across Galleries

view_fotogrids_stats

Neither capability is implied by edit_posts — an editor who can write posts does not get the settings or the stats by default.
Method
Route
Returns
Auth

GET

/library/{type}

Library collections — search, orderby, paging

manage_fotogrids_library

GET

/metadata/tags

The tag vocabulary

edit_posts

GET

/metadata/people

The people vocabulary

edit_posts

GET

/metadata/locations

The location vocabulary

edit_posts

GET

/metadata/item/{id}

Everything recorded against one item

edit_posts

GET

/templates

The template catalogue

edit_posts

POST

/items/{id}/save

Writes item metadata in one transaction

manage_fotogrids

POST

/items/resolve-embed

Resolves a URL to provider and id

manage_fotogrids

POST

/items/embed

Creates an embed item

manage_fotogrids

GET

/picker/items

Backs the item picker — search, type, paging

manage_fotogrids

manage_fotogrids passes everywhere manage_fotogrids_library does, so one admin role covers both.
Permissions

Standard WordPress REST authentication applies

There is no bespoke auth layer. Cookie plus X-WP-Nonce for same-origin admin JavaScript; whatever credential scheme WordPress core already accepts for an external client. Nothing in FotoGrids intercepts, wraps or replaces it — exactly one route verifies a nonce itself, /templates/preview, because it loads inside an iframe.

FotoGrids capabilities

manage_fotogrids

The master capability. Albums, item saves, embeds, cache status and flush, media settings, maintenance, previews, the item picker, core-gallery import and modules.

manage_fotogrids_settings

General, sharing, watermark, SEO, view, advanced and roles settings.

manage_fotogrids_library

The library collections — the most complete collection route on the API.

manage_fotogrids_permissions

The permissions registry, options and simple views.

view_fotogrids_stats

Overview, views, popular Galleries, recent activity and top content.

modify_fotogrids_gallery_settings

Layout, Lightbox, captions, SEO, password and sharing on a Gallery.

modify_fotogrids_album_settings

The same set on an Album.
Core capabilities it reuses

edit_posts

Tags, people, locations, per-item metadata, templates, image sizes, Google Fonts families, catalog field states and entries.

manage_options

The default on GET /gallery/{id}/password. A filter can widen it if your setup needs a narrower role to read it.

auth_callback on meta

fotogrids_featured_image_id is writable over core REST only by a caller with manage_fotogrids on that post.

No parallel model

The checks are the ones your editors already have. Nothing new to map.
Per-object, not per-site

edit_post

Eight editing routes check it against the Gallery or Album named in the URL.

A contributor stays a contributor

An author who can edit their own Gallery can add items to it and set its cover. They cannot touch a Gallery someone else owns.

Album membership runs both ways

Attach from the Gallery side or from the Album side, then reorder from the Album.

The gate holds at the API

Not only in the interface — a script authenticating as that user hits the same wall.
In practice

Four things the routes are already doing

Every one of these runs on a route from the table above. None of them needs a plugin-specific SDK — an HTTP client and an application password is the whole toolchain.

Bulk-import a shoot from your DAM

CSS
import.sh

BASH

				
					curl -u "$WP_USER:$WP_APP_PASSWORD" \
  -X POST https://example.com/wp-json/fotogrids/v1/admin/galleries/42/items \
  -H "Content-Type: application/json" \
  -d '{"attachment_ids":[118,119,120]}'
				
			

Push the files into the Media Library the way you already do, then hand the attachment ids over in one call. Set the cover in the same script with POST /gallery/{id}/featured-item.

Render a Gallery inside a headless front end

CSS
render.sh

BASH

				
					curl -X POST https://example.com/wp-json/fotogrids/v1/gallery/render \
  -H "Content-Type: application/json" \
  -d '{"gallery_id":42,"breakpoint":"mobile","partial":"items_only"}'
				
			

The response carries the whole rendered Gallery, produced by the same code path the theme uses. Send a breakpoint and partial: items_only when you are appending to a grid you already drew.

Warm a Lightbox from a mobile client

CSS
slides.sh

BASH

				
					curl "https://example.com/wp-json/fotogrids/v1/gallery/lightbox/slides" \
  -X POST -H "Content-Type: application/json" \
  -d '{"gallery_id":42,"offset":0,"limit":40}'
				
			

Slide payloads page by offset and limit. GET /lightbox/item/{id} then fills the detail panel for one item: EXIF, credit, filename, filesize, dimensions and MIME type.

Pipe views and shares into your own dashboard

JS
track.js

JS

				
					fetch( '/wp-json/fotogrids/v1/stats/view', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify( { object_type: 'gallery', object_id: 42 } )
} );
				
			

Both stat routes are public, so a front end can record without a key. Read them back with the view_fotogrids_stats routes.

Response anatomy

Every item comes back the same shape

No optional fields and no conditional expansion on GET /gallery/{id} — every entry in items[] carries exactly these keys, in this order.

CSS
response.json

JSON

				
					{
  "id": 42,
  "title": "Coastal Shoot",
  "meta": { "layout": "grid", "columns": 3, "album_id": null },
  "items": [
    {
      "id": 118,
      "position": 0,
      "caption": "Low tide, 6am",
      "description": "",
      "location": "",
      "url":       ".../tide.jpg",
      "thumbnail": ".../tide-150x150.jpg",
      "medium":    ".../tide-300x200.jpg",
      "large":     ".../tide-1024x683.jpg",
      "full":      ".../tide.jpg",
      "alt": "Wet sand at low tide"
    }
  ],
  "shortcode": "<div class="fotogrids-error">FotoGrids: No gallery ID specified. Usage: <div class="fotogrids-error">FotoGrids: Gallery with ID 1 not found.</div></div>"
}
				
			

Two behaviours worth knowing

url and full are the same value — both come from wp_get_attachment_url(). Pick one and stay with it; do not treat a difference between them as meaningful, because there is none.

alt is FotoGrids' own

It reads _wp_attachment_item_alt, not WordPress's _wp_attachment_image_alt, so editing alt text in FotoGrids never touches the Media Library value. It is seeded from that value the first time an item is added to a Gallery, and stored per attachment.

Frequently asked questions

No. The entire content API is in Free — Galleries, Albums, items, rendering, Lightbox, metadata, stats and templates. Nothing you need to read, write or automate a Gallery sits behind a licence. Free is already a full kit. Pro layers on the rest.

Exactly as you would against any WordPress site. Cookie plus X-WP-Nonce from admin JavaScript; whatever credential scheme core accepts for an external client. FotoGrids adds no auth layer of its own, so anything that works against /wp/v2/ works here.

Yes — pass preview=true on GET /gallery/{id}. Without it a non-preview read records a view, so an integration that polls will inflate your own stats. GET /album/{id} increments unconditionally; there is no preview flag on it today.

POST /gallery/render is the paginating route: send page and items_per_page and it answers with page, page_size, total_pages and has_more. The paginated branch drops inlineCss, inlineJs and jsonLd — request page 1 unpaginated if you need those.

Not today. No route registers a schema callback and none subclasses WP_REST_Controller, so OPTIONS self-description is limited to the declared args — which are typed, defaulted and enumerated, and are the contract.

For the post objects, yes. Both types are registered with core REST: /wp/v2/fotogrids-galleries and /wp/v2/fotogrids-albums, served by the stock controller, so core pagination, ordering and _fields all work — including the X-WP-Total headers the custom routes do not send. Items, rendering, Lightbox slides and stats only exist under fotogrids/v1.