For Developers

Integrate your website with WorkPress.

If you're building or maintaining a custom website for a WorkPress customer, this is everything you need to pull published project data and keep it in sync — no account manager required.

Active account requiredRead-only, published dataReal-time via webhooks

Overview

WorkPress is a headless CMS: it's where your customer manages and publishes project data. Your website is its own codebase and hosting — not generated or hosted by WorkPress — but it has no project data of its own. It depends entirely on WorkPress's API to fetch what the customer has published and render it in your own design.

There are two moving pieces:

WorkPress DashboardWhere the customer manages and publishes projects. You never need to touch this.
Your WebsiteFetches published projects from the public API below, at build time or request time.

How It Works

The integration is three pieces, in order of how much you'll touch them:

1FetchCall the public API to list projects or fetch one by slug. It only ever returns published data for organizations with an active WorkPress account.
2RenderBuild pages from the response shape documented below — titles, photos, location, and SEO fields are already generated for you.
3Stay in syncRegister a webhook endpoint so WorkPress can tell your site exactly what changed, instead of you polling or rebuilding on a timer.

Authentication

There's no API key or token on the request itself — endpoints under /api/public/ are called with just an organization ID. But every request is checked against that organization's account status on our side: endpoints only return data for organizations with an active WorkPress account. An org that hasn't been activated, or whose account has lapsed, gets a 403 on every public endpoint — including this one for a project that used to be live.

In practice this means: integrating against this API only works for a customer who is actually on WorkPress. There's nothing here you can stand up independently of a live account.

Webhook calls from WorkPress to your site are separately authenticated with a per-organization shared secret — see Webhooks below.

Replace {orgId} below with the organization ID your customer shares with you from their dashboard settings.

List Projects

Returns every published project for an organization, newest first.

GET/api/public/organizations/{orgId}/projects
Response
[
  {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "name": "Roof Replacement - Oak Lawn",
    "slug": "roof-replacement-oak-lawn",
    "seoTitle": "Roof Replacement in Dallas, TX",
    "metaDescription": "Expert roof replacement services...",
    "services": ["Roof Replacement", "Underlayment"],
    "cover_photo_url": "https://...",
    "address": { "city": "Dallas", "state": "TX" },
    "is_published": true
  }
]

Get Project

Returns a single published project by its SEO-optimized slug.

GET/api/public/organizations/{orgId}/projects/{slug}
Response
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "name": "Roof Replacement - Oak Lawn",
  "slug": "roof-replacement-oak-lawn",
  "seoTitle": "Roof Replacement in Dallas, TX",
  "metaDescription": "Expert roof replacement services...",
  "description": "Full roof replacement with new underlayment...",
  "services": ["Roof Replacement", "Underlayment"],
  "address": {
    "street": "123 Main St",
    "city": "Dallas",
    "state": "TX",
    "zip": "75201"
  },
  "coordinates": { "lat": 32.7767, "lon": -96.7970 },
  "is_published": true,
  "created_at": "2024-01-15T00:00:00.000Z"
}
A 404 here means the slug doesn't exist or the project isn't published yet. A 403 means the organization itself doesn't have an active WorkPress account — see Authentication.

Get Project Photos

Returns the ordered photo gallery for a project.

GET/api/public/organizations/{orgId}/projects/{slug}/photos
Response
[
  {
    "id": "photo_01",
    "url": "https://media.workpressapp.com/...",
    "thumbnail_url": "https://media.workpressapp.com/...",
    "caption": "Finished roof, front elevation",
    "order": 1,
    "type": "before"
  }
]
type is "before" | "after" | "gallery" | null. Only render a before/after comparison slider if at least one photo of each type exists — otherwise show a normal gallery.

Organization Settings

Returns basic business info — useful for footers, schema markup, or contact blocks.

GET/api/public/organizations/{orgId}/settings
Response
{
  "company_name": "Acme Roofing",
  "company_phone": "+1-214-555-0100",
  "company_address": "123 Main St, Dallas, TX 75201",
  "website_url": "https://acmeroofing.com"
}

Data Models

Project

FieldTypeNotes
slugstringSEO-optimized, URL-safe identifier. Use this for routing, not id.
seoTitlestringPre-generated, location-aware page title. Use directly as your <title> / H1.
metaDescriptionstring55–160 characters, ready for your meta description tag.
servicesstring[]1–2 primary services performed, e.g. ["Roof Replacement"].
address / coordinatesobjectStreet-level address and lat/lon for the job site.
is_publishedbooleanAlways true on public endpoints — included for convenience, not filtering.

Photo

FieldTypeNotes
urlstringDirect, publicly-hosted image URL.
thumbnail_urlstringResized thumbnail version of the same image.
captionstringOptional. May be empty.
ordernumberSort ascending for the order the customer arranged in their gallery.
typestring | null"before", "after", "gallery", or null.

Webhooks (Real-Time Sync)

Instead of polling, register an endpoint on your site. When a project is published or updated in the dashboard, WorkPress sends a POST request so you can revalidate just the affected page.

Request headers
POST /your-revalidate-endpoint
x-revalidate-token: <organization's revalidate_secret>
Content-Type: application/json
Payload
{
  "city": "dallas",
  "slug": "roof-replacement"
}

Your endpoint should check the x-revalidate-token header against the secret your customer copies from their dashboard's integration settings, then trigger revalidation (e.g. Next.js revalidatePath / ISR) for that project's page.

Reject any request without a matching token. The secret is unique per organization and rotates from the dashboard if it's ever exposed.

Troubleshooting

No projects showing up, or every request 403s

Confirm the project is Published, not a draft, that you're using the correct organization ID from the customer's dashboard, and that their WorkPress account is active. A 403 on every endpoint for an org that used to work usually means the account lapsed — contact the WorkPress team below.

Updates aren't appearing after publish

If you're not using webhooks, you're likely serving a cached build — rebuild or revalidate on a shorter interval. If you are using webhooks, verify the endpoint URL and shared secret in the dashboard match what your site expects.

Support

Stuck on an integration, or need an organization ID / webhook secret reissued? Reach out and we'll get you unblocked.

Email the WorkPress Team