Extendify API: Redesign
https://ai.extendify.com/api/design
Generate full WordPress website previews by pointing the API at an existing site URL that will be scraped and redesigned.
Typical flow
1. Client calls GET /api/design?url=https://www.customer-site.com
with header: Authorization: Bearer YOUR_TOKEN
2. Gets back { "id": "abc123" }
3. Loads <iframe src="/api/design/abc123/iframe">
4. Iframe shows spinner, then streams final HTML when ready
5. Optionally poll GET /api/design/abc123 for structured data
6. Redirect user to WordPress: /wp-admin/?auto-launch=true&build-id=abc123
Authentication
All requests to GET /api/design require an authentication token sent as a Bearer header:
Authorization: Bearer YOUR_TOKEN
Getting a token: tokens are issued manually by the Extendify team. Reach out to us to get one for your integration.
The token identifies the partner and is used for usage tracking. Read endpoints
(GET /api/design/{id}, GET /api/design/{id}/iframe) are unauthenticated —
the build ID itself acts as the access credential.
Errors
401 Unauthorized— missing, invalid, or revoked token403 url-input-not-permitted— token is not allowed to use the Redesign API. Email Extendify to enable this feature for your token.
Endpoints
GET /api/design?url=...&language=...
Starts a new design preview generation.
| Param | Required | Default | Description |
|---|---|---|---|
url |
Yes | — | An existing site URL to redesign. http(s) only; private/internal hosts are rejected. |
language |
No | en_US |
WordPress locale code (see supported languages below) |
screenshot |
No | false |
Return screenshots as PNGs of the finished preview. This results in a slower response time and consumes additional credit. |
Response 200
{ "id": "abc123" }
Errors
400 invalid-input—urlnot provided, or unsupported language400 url-blocked— URL could not be parsed, used a disallowed scheme, or pointed at a private/loopback host403 url-input-not-permitted— token is not allowed to use the Redesign API. Email Extendify to enable this feature for your token.429— Rate limited
Generation runs asynchronously. Use the ID to poll status or load the iframe.
What we extract from a URL
We extract data like site title, logo, description, menu items, contact information, and more.
Failure modes
These all set status: "error" on the preview row and surface a code in the error field:
| Code | Meaning |
|---|---|
url-unreachable |
DNS / network failure, timeout, non-2xx response, or non-HTML content type |
url-blocked |
Disallowed scheme, private IP, or rejected mid-redirect |
url-too-large |
Response body exceeded 2 MB |
url-low-content |
Page loaded but was too thin to redesign (JS-only shell, captcha, paywall, etc.) |
url-missing-description |
Page scraped but no usable description was extracted (title/nav/logo may be present) |
extract-failed |
AI extraction call itself errored |
unexpected |
Anything else; the message includes the underlying error |
Soft failures are appended to the error field but the preview still completes:
| Code | Meaning |
|---|---|
logo-fallback |
Logo couldn't be fetched/decoded/uploaded — preview fell back to a stock logo |
color-fallback |
Vision color extraction failed — palette chosen without a brand-color hint |
screenshot-failed |
screenshot=true was set but capture failed — preview completes with screenshots: null |
A row may carry several lines in error — soft fallbacks plus, eventually, a hard error. Each line starts with its code so you can branch on it.
GET /api/design/{id}/iframe
Renders the preview as a streamable HTML page. Designed to be loaded in an <iframe>.
| Param | Required | Default | Description |
|---|---|---|---|
loader-color |
No | #9ca3af |
CSS color for the loading spinner (e.g. %2322c55e for green) |
- Shows an animated loader while generation is in progress
- Streams the final HTML once complete
- Times out after ~5 minutes
- Posts
messageevents to the parent window (works cross-origin)
Parent window events — listen with window.addEventListener('message', handler):
event |
height |
Description |
|---|---|---|
loading |
— | Loader is showing, generation in progress |
ready |
number |
Final HTML rendered, includes content height |
resize |
number |
Content height changed (via ResizeObserver) |
error |
— | Generation failed |
timeout |
— | Generation timed out |
All messages have { type: 'extendify-design-preview', event, height? }.
GET /api/design/{id}
Returns the current state of a design preview.
Response 200
{
"id": "abc123",
"status": "complete",
"html": "<!DOCTYPE html>...",
"screenshots": [
{
"slug": "home",
"raw": "https://...",
"regular": "https://...",
"small": "https://...",
"thumb": "https://..."
}
],
"error": null
}
status is complete when the preview is ready, error on failure, or one of these in-flight values:
starting,generating-profile,generating-content,generating-images— the original description-only pipelinefetching-url,extracting-content,processing-logo— only seen on URL-mode requestscapturing-screenshot— only seen whenscreenshot=true, just beforecomplete
Screenshots
screenshots has one entry per page, each carrying the same PNG in four widths:
| Size | Width | Typical weight |
|---|---|---|
raw |
1280px | 280 KB – 1 MB |
regular |
1080px | 100 – 270 KB |
small |
400px | 20 – 55 KB |
thumb |
200px | 8 – 20 KB |
Important: every screenshot URL is signed and expires within approximately 30 minutes. We recommend downloading the image and hosting it yourself rather than hot-linking to it.
The response also includes additional fields consumed server-side by the WordPress redirect flow. Their shape is internal — don't rely on it.
WordPress redirect
Once the user is happy with the preview, redirect them to their WordPress admin to apply the design:
https://{user-site}/wp-admin/?auto-launch=true&build-id={id}
| Param | Description |
|---|---|
auto-launch |
Must be true — triggers the Extendify launch flow on page load |
build-id |
The design preview ID returned from /api/design |
Supported languages
See extendify.com/documentation/supported-languages
Credit usage
| Request | Credits |
|---|---|
| Single page scrape | 5 |
| Single page scrape with screenshot | 6 |