Skip to main content

Landing pages

CRUD for landing pages — single-product conversion pages with sections (image carousels, order forms, fake visitors, countdowns, special offers).

Written by Support

A landing page is a focused, single-product conversion page. They're independent of the storefront catalogue — you can have a landing page with no live product (for upcoming launches), or one tied to a specific product for paid ads.

Sections (image carousels, fake visitors, countdowns, etc.) are managed in the dashboard at v1; the API CRUDs the parent record only. A v1.1 update will expose section CRUD too.

Plan limits

Plan

Landing pages (all statuses — drafts count)

Free

0 (one-time purchase: 1000 DZD/lifetime each)

Pro

3

Unlimited / Enterprise

unlimited

The cap is enforced by the dashboard create/duplicate flows only, counting every landing page including drafts. The API enforces nothing: POST /v1/landing-pages followed by /publish bypasses the cap entirely, and on a paid plan the extra pages render live on the storefront. Free-plan pages stay invisible unless the page was purchased (is_purchased).

GET /v1/landing-pages

List landing pages. Cursor-paginated. Cached for 30 s — check the X-Cache: HIT|MISS response header. GET /v1/landing-pages/{id} is not cached.

Auth: any active platform key for the store (landing_pages:read is not enforced at v1; only landing_pages:write is checked, on the write endpoints).

Query parameters

Param

Type

Notes

limit

int 1–200

Default 50

cursor

string

Opaque

status

active | draft

Filter

An unrecognised status is ignored, returning all pages rather than a 400.

Response 200

{
  "data": {
    "items": [
      {
        "id":            42,
        "title":         "Black T-Shirt — 30% off",
        "slug":          "black-tshirt-30-off",
        "status":        "active",
        "language":      "ar",
        "product_id":    26,
        "views":         1543,
        "is_purchased":  false,
        "created_at":    "2026-03-01 10:00:00",
        "updated_at":    "2026-03-15 14:22:11"
      }
    ],
    "next_cursor": null,
    "has_more": false
  }
}

GET /v1/landing-pages/{id}

Detail with section_count.

{
  "data": {
    "id":               42,
    "title":            "Black T-Shirt — 30% off",
    "slug":             "black-tshirt-30-off",
    "status":           "active",
    "language":         "ar",
    "product_id":       26,
    "views":            1543,
    "is_purchased":     false,
    "meta_title":       "Black T-Shirt — Cotton 200gsm — 30% off | DZBuild",
    "meta_description": "Limited-time offer on our cotton black t-shirt.",
    "section_count":    7,
    "created_at":       "2026-03-01 10:00:00",
    "updated_at":       "2026-03-15 14:22:11"
  }
}

Field reference

Field

Notes

status

Strict active or draft only — there is no archived state for landing pages.

language

ar, fr or en.

product_id

The linked product, or null. A page with no product id cannot price its order form correctly.

views

Read-only. Counted each time the public page is viewed; the API cannot write it and there is no way to reset it.

is_purchased

true once the page has been bought outright (1000 DZD/lifetime). On the Free plan this is what makes the page visible on the storefront.

section_count

Detail endpoint only — a live count of the page's sections, computed per request.

meta_title / meta_description

SEO tags. See the note under create.

POST /v1/landing-pages — create

Auth: platform key with landing_pages:write. Requires Idempotency-Key.

Body

Field

Type

Required

Notes

title

string 1–255

slug

string

Auto-derived from title if omitted. A slug you supply here is stored without normalisation — send a clean one

status

active | draft

Default draft. Any other value is silently coerced to draft

language

ar | fr | en

Default ar. Any other value is silently coerced to ar

product_id

int

Must belong to your store; the page links to this product

meta_title

string ≤ 255

SEO title. Omit it via the API and it is stored and returned as null (unlike the dashboard form, which copies title into it). The public page still renders title as a fallback, so the visible page title is correct either way

meta_description

string

SEO description

Slugs are made unique within your store by appending -2, -3, … An empty slug base falls back to landing- plus 6 hex characters.

Errors

Code

Cause

bad_request "Body must be valid JSON"

Wrong Content-Type or malformed JSON

bad_request "title is required (1-255 chars)"

Missing or over-long title

bad_request "product_id N does not belong to this store"

Cross-store id

Request

curl -X POST 'https://api.dzbuild.app/v1/landing-pages' \
  -H "Authorization: Bearer $DZ_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "title":      "Black T-Shirt — 30% off",
    "language":   "ar",
    "product_id": 26,
    "status":     "draft"
  }'

Returns 200 (not 201) and the same shape as GET /v1/landing-pages/{id}. The new landing page has zero sections — populate them in the dashboard.

PATCH /v1/landing-pages/{id}

Partial update.

PATCH validates more strictly than create: an invalid status returns 400 bad_request ("status must be active or draft") and an invalid language returns 400 ("language must be ar, fr, or en") instead of being coerced. title must still be 1–255 characters. A slug sent on PATCH is normalised, unlike on create.

curl -X PATCH 'https://api.dzbuild.app/v1/landing-pages/42' \
  -H "Authorization: Bearer $DZ_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ "title": "Black T-Shirt — Spring promo" }'

Renaming auto-regenerates slug only if you didn't pass slug explicitly.

POST /v1/landing-pages/{id}/publish

Convenience: flip status to active. Equivalent to PATCH ... { status: "active" }.

curl -X POST 'https://api.dzbuild.app/v1/landing-pages/42/publish' \
  -H "Authorization: Bearer $DZ_KEY" \
  -H "Idempotency-Key: publish-42-$(date +%s)"

DELETE /v1/landing-pages/{id}

Hard delete. The page's sections are removed with it.

curl -X DELETE 'https://api.dzbuild.app/v1/landing-pages/42' \
  -H "Authorization: Bearer $DZ_KEY" \
  -H "Idempotency-Key: del-42"

Response: { "data": { "deleted": true, "id": 42 } }.

Did this answer your question?