Website Pages

7 views Markdown

The seven endpoints for pages, contracts, news, blog posts and references.

Overview

The panel's Pages, Contracts, News, Blog and References tabs are all one content type. All five are managed through these seven endpoints, and the only thing separating them is the type you send.

Content is kept per language: title, address, body and search-engine fields each live separately in every language. The list gives you the current language while the detail gives you all of them, so translation work starts at the detail.

Images are uploaded through their own endpoints and named by kind. Which kinds are valid depends on the page type. The same call can work on one type and be refused on another.

Reference

Listing the Pages

get/api/v1/admin/website/pages
Website/GetPages admin

Returns the pages of the content type you pick.

Query 4
typestringWhich content type: normal, contract, news, articles, references. The plain page by default.
searchstringSearches the titles.
pageintWhich page.
limitintRecords per page. A hundred at most.
Response fields data[] — 6 + meta — 5
idintThe page id.
typestringThe content type.
titlestringIts title in the current language.
routestringIts address in the current language.
categorystringThe name of its category.
created_atstringWhen it was created.
totalintHow many there are. It comes back under meta.
pageintThe page you are on.
limitintThe page size.
type stringThe content type filtered on.
next_pageintThe next page. Zero means you are on the last one.
Errors 2
invalid_type422The content type is not recognised.
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/website/pages?type=news&limit=25' \
  -H "Authorization: Bearer $API_KEY"
const url = new URL('https://panel.example.com/api/v1/admin/website/pages');
url.searchParams.set('type', 'news');

const res  = await fetch(url, {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/website/pages?' . http_build_query(['type' => 'news', 'limit' => 25]));
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Leave the type out and only PLAIN pages come back; news lives at the same endpoint.
$news = Api::Website()->GetPages([], ['type' => 'news'])['data'];

Reading One Page

get/api/v1/admin/website/pages/{id}
Website/GetPage admin

Returns one page with all its languages and images.

Response fields data — 12
idintThe page id.
typestringThe content type: normal, contract, news, articles, references.
categoryintThe category it belongs to.
sidebarstringWhether the sidebar shows.
statusstringWhether the page is live.
visibilitystring | nullWhether it appears in listings.
visible_to_userint | nullWhether it shows in the client panel.
rankint | nullWhere it sits in the listing.
optionsobjectThe options belonging to that type. The contract switches and the search-engine preference live here.
created_atstring | nullWhen it was created.
languagesobjectThe content per language: title, route, body, search-engine fields and, on a reference, its extra texts.
imagesobjectThe image address per kind. Only the kinds that type allows.
Errors 2
page_not_found404No such page.
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/website/pages/5' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch(`https://panel.example.com/api/v1/admin/website/pages/${id}`, {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/website/pages/' . $id);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The list gives ONE language and the detail gives them ALL; translation work starts here.
$page = Api::Website()->GetPage(['id' => $id])['data'];
$en   = $page['languages']['en'] ?? null;

Creating a Page

post/api/v1/admin/website/pages
Website/CreatePage admin the type is fixed

Opens a new page and writes its languages.

Body 15
typestringreqThe content type: normal, contract, news, articles, references. It cannot be changed later.
languagesobjectreqThe content per language: title, route, body and search-engine fields. A title is needed in each language you send.
statusstringWhether the page is live. Live by default.
sidebarstringWhether the sidebar shows.
categoryintThe category the page belongs to.
seo_indexintLets search engines index the page.
imagesobjectImages to upload in the same call. A kind the type does not allow fails the call.
show_during_account_registrationintShows during sign-up. Contract type only.
show_during_purchaseintShows during checkout. Contract type only.
show_in_account_preferencesintShows in account preferences. Contract type only.
mandatory_account_preferencesintMakes acceptance required in account preferences. Contract type only.
visibilitystringWhether the page appears in listings. News and reference types only.
visible_to_userintShows in the client panel as well. News type only.
rankintWhere it sits in the listing. Reference type only.
websitestringThe reference's address. Reference type only.
Response fields 201 — data — 12
dataobjectThe page created. Same shape as the detail endpoint.
Errors 7
invalid_type422The content type is not recognised.
languages_required422No language was sent.
title_required422A title is empty in one language.
route_exists422That address is already in use in that language.
invalid_kind422The image kind does not suit this type.
create_failed500The page could not be created.
insufficient_scope403The key lacks the required scope.
Request
curl -X POST 'https://panel.example.com/api/v1/admin/website/pages' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"type":"normal","languages":{"tr":{"title":"Hakkimizda","content":"<p>Merhaba</p>"}}}'
const res = await fetch('https://panel.example.com/api/v1/admin/website/pages', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    type: 'normal',
    languages: {
      en: { title: 'About Us', content: '<p>Hello</p>' },
    },
  }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/website/pages');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'type'      => 'normal',
        'languages' => ['en' => ['title' => 'About Us', 'content' => '<p>Hello</p>']],
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Leave the address out and it is built from the title; a clash in that language returns 422.
Api::Website()->CreatePage([
    'type'      => 'news',
    'languages' => ['en' => ['title' => 'Maintenance notice']],
]);

Updating a Page

patch/api/v1/admin/website/pages/{id}
Website/UpdatePage admin

Changes the page fields and languages you send.

Body 14
languagesobjectreqThe content per language: title, route, body and search-engine fields. A title is needed in each language you send.
statusstringWhether the page is live. Live by default.
sidebarstringWhether the sidebar shows.
categoryintThe category the page belongs to.
seo_indexintLets search engines index the page.
imagesobjectImages to upload in the same call. A kind the type does not allow fails the call.
show_during_account_registrationintShows during sign-up. Contract type only.
show_during_purchaseintShows during checkout. Contract type only.
show_in_account_preferencesintShows in account preferences. Contract type only.
mandatory_account_preferencesintMakes acceptance required in account preferences. Contract type only.
visibilitystringWhether the page appears in listings. News and reference types only.
visible_to_userintShows in the client panel as well. News type only.
rankintWhere it sits in the listing. Reference type only.
websitestringThe reference's address. Reference type only.
Response fields data — 12
dataobjectThe page as it now stands. Same shape as the detail endpoint.
Errors 5
page_not_found404No such page.
title_required422A title was emptied in one language.
route_exists422That address is already in use in that language.
invalid_kind422The image kind does not suit this type.
insufficient_scope403The key lacks the required scope.
Request
curl -X PATCH 'https://panel.example.com/api/v1/admin/website/pages/5' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"status":"inactive","languages":{"tr":{"title":"Sirketimiz"}}}'
const res = await fetch(`https://panel.example.com/api/v1/admin/website/pages/${id}`, {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    status: 'inactive',
    languages: { en: { title: 'About Our Company' } },
  }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/website/pages/' . $id);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PATCH',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'status'    => 'inactive',
        'languages' => ['en' => ['title' => 'About Our Company']],
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Only the language you send is written and the rest are KEPT; the type field is ignored.
Api::Website()->UpdatePage([
    'id'        => $id,
    'languages' => ['en' => ['title' => 'About Our Company']],
]);

Deleting a Page

delete/api/v1/admin/website/pages/{id}
Website/DeletePage admin

Removes a page along with all its languages.

Response fields data — 2
deletedboolWhether the delete ran.
idintThe id of the page removed.
Errors 3
page_not_found404No such page.
blocked_by_gate422A hook refused the delete.
insufficient_scope403The key lacks the required scope.
Request
curl -X DELETE 'https://panel.example.com/api/v1/admin/website/pages/5' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch(`https://panel.example.com/api/v1/admin/website/pages/${id}`, {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/website/pages/' . $id);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// To take a page down, switch its STATUS off rather than delete: the address survives.
Api::Website()->UpdatePage(['id' => $id, 'status' => 'inactive']);

Uploading a Page Image

put/api/v1/admin/website/pages/{id}/images/{kind}
Website/UploadPageImage admin

Uploads a page image and puts it in place of the one before.

Path 2
idintThe page id.
kindstringThe image kind: header-background, cover, mockup. The cover suits news, blog posts and references, while the mock-up suits references alone.
Body 1
imagestringreqThe image to upload. Either an address or the data itself.
Response fields 201 — data — 2
kindstringThe kind uploaded.
urlstringThe image's public address.
Errors 3
page_not_found404No such page.
invalid_kind422The image kind does not suit this type.
insufficient_scope403The key lacks the required scope.
Request
curl -X PUT 'https://panel.example.com/api/v1/admin/website/pages/5/images/header-background' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"image":"https://ornek.com/afis.jpg"}'
const res = await fetch(`https://panel.example.com/api/v1/admin/website/pages/${id}/images/header-background`, {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ image: 'https://example.com/banner.jpg' }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/website/pages/' . $id . '/images/header-background');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['image' => 'https://example.com/banner.jpg']),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The cover and mock-up kinds also BUILD a thumbnail; the banner kind leaves one file.
Api::Website()->UploadPageImage([
    'id' => $id, 'kind' => 'cover', 'image' => $data,
]);

Removing a Page Image

delete/api/v1/admin/website/pages/{id}/images/{kind}
Website/DeletePageImage admin

Removes a page image along with its thumbnail.

Path 2
idintThe page id.
kindstringThe image kind to remove: header-background, cover, mockup.
Response fields data — 3
deletedboolWhether the delete ran.
idintThe page id.
kindstringThe kind removed.
Errors 3
page_not_found404No such page.
invalid_kind422The image kind does not suit this type.
insufficient_scope403The key lacks the required scope.
Request
curl -X DELETE 'https://panel.example.com/api/v1/admin/website/pages/5/images/header-background' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch(`https://panel.example.com/api/v1/admin/website/pages/${id}/images/header-background`, {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/website/pages/' . $id . '/images/header-background');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// To REPLACE an image there is no need to delete first; the upload takes its place.
Api::Website()->DeletePageImage(['id' => $id, 'kind' => 'cover']);

Pitfalls

The type is chosen only at creation

The content type is part of what a record is, and the update ignores it. A record opened as a plain page cannot become a news item. You have to create it again with the right type and remove the old one. Getting the type wrong costs the address and the images as well.

The address is unique per language

The same address can sit side by side in different languages, yet two pages in one language cannot share it. The clash error names the language it happened in. Leave the address out and it is built from the title, so two news items with similar titles can collide unexpectedly.

The image kind depends on the page type

The banner suits every type. The cover is taken only on news, blog posts and references, and the mock-up only on references. A kind that does not suit comes back as a 422. This holds at creation too: an invalid kind in the body means the page is never created at all.

Type-bound fields sit silently on the others

The contract acceptance switches work on contracts alone. So do showing a news item in the client panel, and a reference's rank and address. Sent on another type they raise no error and do nothing. When behaviour does not follow, check the record's type first.

The update merges languages

On an update the languages you send are written and the ones you leave out are kept. Correcting one language does not mean carrying the others along. This differs from some other write endpoints, where the body counts as the whole definition and whatever is missing gets dropped.

Was this helpful?

Thanks for your feedback!

Still Need Help?

Our support team is here around the clock for anything you can't find above.