Console API
Console API allows you to do administrative tasks of a blog. This is the same API we use internally in the Console. You can use it to automate some tasks or even build a completely new mini-console by yourself.
Calling the API
- API Basepath:
https://blogs.hyvor.com/api/console/v0/blog/{subdomain} - Create a Console API Key from the Console and send it as the
X-API-KEYheader. - Console API endpoints use the following HTTP methods.
GET- to get data, usually an array of resourcesPOST- to create a resourcePATCH- to partially or completely update a resourceDELETE- to delete a resource
- Similarly to our Data API, the Console API always return an object or an array of objects, in JSON format
- Request params can be set as JSON (recommended) or as usual request params (in query or HTTP body)
- In this documentation, objects, request params, and responses are written as Typescript interfaces in order to make type declarations concise.
Categories
The Console API has many endpoints and is categorized by what “resource” you want to access or manage. Most categories have CRUD operations but some may have more endpoints for specific tasks. These objects are defined within the Category. Also, note that Console API objects are different from Data API objects.
Jump to each category:
- Blog
- Posts & Pages
- Tags
- Users
- Media
- Navigation
- Languages
- Redirects
- Webhooks
- Theme Files
- Export
- Link Analysis
- Route
- Misc
Blog
Endpoints:
GET /blog- Get blog dataPATCH /blog- Update blog dataPOST /blog/variant- Create a blog variantPATCH /blog/variant- Update a blog variant
Objects:
Get blog data
GET /blog
type Request = {};
type Response = Blog;Update blog data
PATCH /blog
type Request = Partial<Blog>; // except id and variants
type Response = Blog;Create a blog variant
POST /blog/variant
type Request = {
language_id: number;
};
type Response = BlogVariant;Update a blog variant
PATCH /blog/variant
type Request = {
language_id: number;
name?: string;
description?: string;
};
type Response = BlogVariant;Posts & Pages
Endpoints:
GET /posts- Get postsGET /pages- Get pagesPOST /post- Create a post/pageGET /post/{id}- Get a post/pagePATCH /post/{id}- Update a post/pageDELETE /post/{id}- Delete a post/pagePOST /post/{id}/variant- Create a post variantPATCH /post/{id}/variant- Update a post variantPOST /post/{id}/variant/publish- Publish a post variantPOST /post/{id}/variant/unpublish- Unpublish a post variantDELETE /post/{id}/variant- Delete a post variantPATCH /post/{id}/tags- Update post tagsPATCH /post/{id}/authors- Update post authors
Objects:
Get posts
Get posts with filtering. The filter parameters are similar to the ones in the Console. Returns a lightweight PostListItem per post, rather than the full Post object - fetch GET /post/{id} for the full post.
GET /posts
type Request = {
status?: 'featured' | 'published' | 'draft' | 'scheduled';
author_id?: number;
tag_id?: number;
start_timestamp?: number; // unix timestamp
end_timestamp?: number; // unix timestamp
search?: string;
language_id?: number; // defaults to the blog's primary language
limit?: number; // default 50, max 100
offset?: number;
};
type Response = PostListItem[];Get pages
Same lightweight PostListItem shape as GET /posts.
GET /pages
type Request = {};
type Response = PostListItem[];Create a post/page
Create an empty draft post. A post variant will be created from the primary language of the blog.
POST /post
type Request = {
is_page?: boolean; // default to false
};
type Response = Post;Get a post/page
GET /post/{id}
type Request = {};
type Response = Post;Update a post/page
PATCH /post/{id}
type Request = {
is_featured?: boolean;
featured_image_url?: string | null;
canonical_url?: string | null;
code_head?: string | null;
code_foot?: string | null;
published_at?: number | null; // unix timestamp
};
type Response = Post;Delete a post/page
DELETE /post/{id}
type Request = {};
type Response = {};Create a post variant
POST /post/{id}/variant
type Request = {
language_id: number;
};
type Response = PostVariant;Update a post variant
PATCH /post/{id}/variant
type Request = {
language_id: number;
slug?: string; // max 255 chars
content?: string | null;
content_unsaved?: string | null;
title?: string | null; // max 255 chars
description?: string | null; // max 255 chars
};
type Response = PostVariant;content and content_unsaved should be in ProseMirror JSON format. See Get ProseMirror JSON endpoint to convert HTML to ProseMirror JSON.
Publish a post variant
POST /post/{id}/variant/publish
type Request = {
language_id: number;
};
type Response = PostVariant;Publishes a post variant. If the variant does not have a slug, one is automatically generated from the title. If the post does not have a published_at time, it is set to now. Requires posts.publish.own scope.
Unpublish a post variant
POST /post/{id}/variant/unpublish
type Request = {
language_id: number;
};
type Response = PostVariant;Sets the variant status back to draft. Works on both published and scheduled variants. Requires posts.publish.own scope.
Delete a post variant
DELETE /post/{id}/variant
type Request = {
language_id: number;
};
type Response = {};Update post tags
PATCH /post/{id}/tags
type Request = {
ids: number[]; // tag IDs
};
type Response = {};Update post authors
PATCH /post/{id}/authors
type Request = {
ids: number[]; // author (user) IDs
};
type Response = {};Tags
Endpoints:
GET /tags- Get or search tagsPOST /tag- Create a tagPATCH /tag/{id}- Update a tagDELETE /tag/{id}- Delete a tagPOST /tag/{id}/variant- Create a tag variantPATCH /tag/{id}/variant- Update a tag variantDELETE /tag/{id}/variant- Delete a tag variant
Objects:
Get or search tags
Lists tags, optionally searching by name (primary language).
GET /tags
type Request = {
limit?: number; // default 50, max 100
offset?: number;
search?: string; // filters tags by name (primary language)
};
type Response = Tag[];Create a tag
POST /tag
type Request = {
name: string; // name for the primary language variant
is_private: boolean; // default false
};
type Response = Tag;Update a tag
PATCH /tag/{id}
type Request = {
is_private?: boolean;
slug?: string;
code_head?: string | null;
code_foot?: string | null;
};
type Response = Tag;Delete a tag
DELETE /tag/{id}
type Request = {};
type Response = {};Create a tag variant
POST /tag/{id}/variant
type Request = {
language_id: number;
};Update a tag variant
PATCH /tag/{id}/variant
type Request = {
language_id: number;
name?: string;
description?: string | null;
};Delete a tag variant
DELETE /tag/{id}/variant
type Request = {
language_id: number;
};Users
Endpoints:
GET /users- Get usersGET /users/search- Search usersPOST /user- Create a userPOST /user/guest- Create a guest userPATCH /user/{id}- Update a userDELETE /user/{id}- Delete a userPOST /user/{id}/variant- Create a user variantPATCH /user/{id}/variant- Update a user variantDELETE /user/{id}/variant- Delete a user variant
Objects:
Get users
GET /users
type Request = {
offset?: number;
};
type Response = User[];Search users
Searches for users by name.
GET /users/search
type Request = {
search: string;
};
type Response = User[];Create a user
POST /user
type Request = {
username_or_email: string;
role: 'owner' | 'admin' | 'editor' | 'writer' | 'contributor';
};
type Response = User;Create a guest user
POST /user/guest
type Request = {
name: string;
};
type Response = User;Update a user
PATCH /user/{id}
type Request = {
hyvor_user_id?: number;
role?: 'owner' | 'admin' | 'editor' | 'writer' | 'contributor';
status: 'active' | 'blocked';
slug: string;
email?: string;
website_url?: string;
picture_url?: string;
social_facebook?: string;
social_twitter?: string;
social_linkedin?: string;
social_youtube?: string;
social_tiktok?: string;
social_instagram?: string;
social_github?: string;
};
type Response = User;Delete a user
DELETE /user/{id}
type Request = {};
type Response = {};Create a user variant
POST /user/{id}/variant
type Request = {};
type Response = UserVariant;Update a user variant
PATCH /user/{id}/variant
type Request = {
name?: string;
bio?: string;
location?: string;
};
type Response = UserVariant;Delete a user variant
DELETE /user/{id}/variant
type Request = {};
type Response = {};Media
Endpoints:
GET /media- Get mediaPOST /media- Create a mediaPOST /media/from-url- Create a media from URLDELETE /media/{id}- Delete a navigationGET /media/unsplash/search- Get media from unsplashPATCH /media- Patch media
Objects:
Get media
GET /media
type Request = {
limit: number;
offset: number;
search?: string;
extensions?: string[];
type?: string;
};
type Response = Media[];Create a media
POST /media
type Request = {
file: File;
post_id: number;
};
type Response = Media;Create a media from URL
POST /media/from-url
type Request = {
url: string;
post_id?: number;
};
type Response = Media;Delete a media
DELETE /media/{id}
type Request = {};
type Response = {};Patch a media
PATCH /media/{id}
type Request = Partial<Media>;
type Response = Media;Navigation
Endpoints:
GET /navigations- Get navigationsPATCH /navigations/sort- Update sort navigationsPOST /navigation- Create a navigationPATCH /navigation/{id}- Update a navigationDELETE /navigation/{id}- Delete a navigationPOST /navigation/{id}/variant- Create a navigation variantPATCH /navigation/{id}/variant- Update a navigation variantDELETE /navigation/{id}/variant- Delete a navigation variant
Objects:
Get navigations
GET /navigations
type Request = {};
type Response = Navigation[];Update sort navigations
PATCH /navigations/sort
type Request = {
ids?: number[];
};
type Response = {};Create a navigation
POST /navigation
type Request = {
url: string;
name: string;
type: 'header' | 'footer';
};
type Response = Navigation;Update a navigation
PATCH /navigation/{id}
type Request = {
url: string;
type: 'header' | 'footer';
};
type Response = Navigation;Delete a navigation
DELETE /navigation/{id}
type Request = {};
type Response = {};Create a navigation variant
POST /navigation/{id}/variant
type Request = {
language_id: number;
name?: string;
};
type Response = NavigationVariant;Update a navigation variant
PATCH /navigation/{id}/variant
type Request = {
language_id: number;
name: string;
};
type Response = NavigationVariant;Delete a navigation variant
DELETE /navigation/{id}/variant
type Request = {
language_id: number;
};
type Response = {};Language
Endpoints:
GET /languages- Get languagesPOST /language- Create a languagePATCH /language/{id}- Update a languageDELETE /language/{id}- Delete a language
Objects:
Get languages
GET /languages
type Request = {};
type Response = Languages[];Create a language
POST /language
type Request = {
code: string; // max 12 chars
name: string; // max 255 chars
direction: 'ltr' | 'rtl';
};
type Response = Language;Update a language
PATCH /language/{id}
type Request = {
code: string; // max 12 chars
name: string; // max 255 chars
direction: 'ltr' | 'rtl';
};
type Response = Language;Delete a language
DELETE /language/{id}
type Request = {};
type Response = {};Redirect
Endpoints:
GET /redirects- Get redirectsPOST /redirect- Create a redirectPATCH /redirect/{id}- Update a redirectDELETE /redirect/{id}- Delete a redirect
Objects:
Get redirects
GET /redirects
type Request = {
search?: string;
limit?: number;
offset?: number;
};
type Response = Redirect[];Create a redirect
POST /redirect
type Request = {
dynamic: boolean;
path: string;
to: string;
type: 'temporary' | 'permanent';
};
type Response = Redirect;Update a redirect
PATCH /redirect/{id}
type Request = {
path?: string;
to?: string;
type?: 'temporary' | 'permanent';
};
type Response = Redirect;Delete a redirect
DELETE /redirect/{id}
type Request = {};
type Response = {};Webhook
Endpoints:
GET /webhooks- Get webhooksPOST /webhook- Create a webhookPATCH /webhook/{id}- Update a webhookDELETE /webhook/{id}- Delete a webhook
Objects:
Get webhooks
GET /webhooks
type Request = {};
type Response = Webhook[];Create a webhook
POST /webhook
type Request = {
url: string;
events: 'cache.single' | 'cache.templates' | 'cache.all'[];
};
type Response = Webhook;Update a webhook
PATCH /webhook/{id}
type Request = {
url?: string;
events?: 'cache.single' | 'cache.templates' | 'cache.all'[];
};
type Response = Webhook;Delete a webhook
DELETE /webhook/{id}
type Request = {};
type Response = {};Theme Files
Endpoints:
GET /theme/files- Get theme filesPOST /theme/file- Create a theme filePATCH /theme/file/{id}- Update a theme fileDELETE /theme/file/{id}- Delete a theme file
Objects:
Get theme files
GET /theme/files
type Request = {};
type Response = FileObject[];Create a theme file
POST /theme/file
type Request = {
folder: 'templates' | 'assets' | 'styles' | 'lang';
name: string;
content?: string;
file: File;
};
type Response = FileObject;Update a theme file
PATCH /theme/file/{id}
type Request = {
name?: string;
content?: string;
};
type Response = FileObject;Delete a theme file
DELETE /theme/file/{id}
type Request = {};
type Response = {};Export
Endpoints:
GET /exports- Get exportsPOST /export- Create an export
Objects:
Get exports
GET /exports
type Request = {};
type Response = ExportObject[];Create an export
POST /export
type Request = {};
type Response = ExportObject;Link Analysis
Endpoints:
POST /link-analysis/check-urls- Check post variant linkPATCH /link-analysis/ignore-link- Ignore a linkGET /link-analysis/stats- Get link statisticsGET /link-analysis/links- Get linksGET /link-analysis/checks- Get checksPOST /link-analysis/check- Create a check
Objects:
Check post variant link
POST /link-analysis/check-urls
type Request = {
post_variant_id: number;
urls: string[];
force?: boolean;
};
type Response = LinkObject[];Ignore a link
PATCH /link-analysis/ignore-link
type Request = {
post_variant_id: number;
urls: string[];
status: boolean;
};
type Response = LinkObject;Get link statistics
GET /link-analysis/stats
type Request = {};
type Response = {
counts: number;
};Get links
GET /link-analysis/links
type Request = {
type?: 'ok' | 'broken' | 'ignored' | 'redirected';
limit?: number;
offset?: number;
};
type Response = LinkObject[];Get checks
GET /link-analysis/checks
type Request = {
limit?: number;
offset?: number;
};
type Response = CheckObject[];Create a check
POST /link-analysis/check
type Request = {};
type Response = CheckObject;Route
Endpoints:
GET /routes- Get routesPOST /route- Create a routePATCH /route/{id}- Update a routeDELETE /route/{id}- Delete a route
Objects:
Get routes
GET /routes
type Request = {};
type Response = Route[];Create a route
POST /route
type Request = {
name: string;
match: string;
template: string;
post_filter?: string;
content_type?: string;
};
type Response = Route;Update a route
PATCH /route/{id}
type Request = {
name: string;
match: string;
template: string;
post_filter?: string;
content_type?: string;
};
type Response = Route;Delete a route
DELETE /route/{id}
type Request = {};
type Response = {};Misc
Endpoints:
GET /misc/themes- Get all themesGET /misc/prosemirror/json- Get prosemirror jsonDELETE /blog/cache- Delete blog cacheDELETE /blog- Delete the blog
Get all themes
GET /misc/themes
type Request = {};
type Response = Theme[];Get prosemirror JSON from HTML
GET /misc/prosemirror/json
type Request = {
html: string;
};
type Response = {
json: string;
};Delete blog cache
DELETE /blog/cache
type Request = {
type: 'all' | 'template' | 'paths';
paths?: string[];
};
type Response = {};Delete the blog
Soft-deletes the blog. The blog and its data are permanently deleted 30 days later. Requires the blog.delete scope.
DELETE /blog
type Request = {};
type Response = {};Objects
Blog Object
interface Blog {
id: number;
created_at: number;
is_blocked: boolean;
subdomain: string;
type: 'default' | 'dev';
hosting_at: 'subdomain' | 'domain' | 'self';
hosting_domain: string | null;
hosting_url: string | null;
embeddable: boolean;
embedding_domains: string | null;
logo_url: string | null;
cover_url: string | null;
social_facebook: string | null;
social_twitter: string | null;
social_linkedin: string | null;
social_youtube: string | null;
social_tiktok: string | null;
social_instagram: string | null;
social_github: string | null;
code_head: string | null;
code_foot: string | null;
seo_indexing: boolean;
seo_robots_txt: string | null;
seo_external_links_follow: 'follow' | 'nofollow';
comments_code: string | null;
newsletter_code: string | null;
color_modes: 'light' | 'dark' | 'both';
color_mode_default: 'light' | 'dark' | 'os';
syntax_on: boolean;
syntax_line_numbers: boolean;
syntax_theme: string | null;
flashload: boolean;
variants: BlogVariant[];
}BlogVariant Object
interface BlogVariant {
language_id: number;
name: string | null;
description: string | null;
}Post Object
interface Post {
id: number;
preview_id: string;
created_at: number;
updated_at: number;
published_at: number | null;
is_featured: boolean;
is_page: boolean;
featured_image_url: string | null;
canonical_url: string | null;
code_head: string | null;
code_foot: string | null;
variant_statuses: {
id: number;
language_id: number;
status: 'draft' | 'published' | 'scheduled';
}[];
tags: Tag[];
authors: User[];
}variant_statuses only tells you which languages a post has and their status. Fetch GET /post/{id}?variant_language_code=... to get the full PostVariant object (content, title, SEO fields, etc.) for a single language.
PostVariant Object
interface PostVariant {
language_id: number;
slug: string | null;
status: 'draft' | 'published' | 'scheduled';
url: string;
content: string | null;
content_unsaved: string | null;
title: string | null;
description: string | null;
}PostListItem Object
Returned by GET /posts and GET /pages. A lightweight per-post summary: slug, url, title, and link_analysis reflect the variant of the requested (or blog’s primary) language, and tags/authors are just their primary-language names. Fetch GET /post/{id} for the full Post object, including tags and authors.
interface PostListItem {
id: number;
created_at: number;
updated_at: number;
published_at: number | null;
is_featured: boolean;
is_page: boolean;
slug: string | null;
url: string | null;
title: string | null;
link_analysis: Record<string, number>;
variant_statuses: {
language_id: number;
status: 'draft' | 'published' | 'scheduled';
}[];
tags: string[]; // tag names, primary language
authors: string[]; // author names, primary language
}Tag Object
interface Tag {
id: number;
created_at: number;
updated_at: number;
is_private: boolean;
slug: string;
posts_count: number;
code_head: string | null;
code_foot: string | null;
variants: TagVariant[];
}TagVariant Object
interface TagVariant {
language_id: number;
url: string | null;
name: string | null;
description: string | null;
}User Object
interface User {
id: number;
created_at: number;
updated_at: number;
hyvor_user_id: number | null;
status: 'invited' | 'active' | 'blocked';
role: 'owner' | 'admin' | 'editor' | 'writer' | 'contributor';
slug: string;
posts_count: number;
email: string;
picture_url: string | null;
website_url: string | null;
social_facebook: string | null;
social_twitter: string | null;
social_linkedin: string | null;
social_youtube: string | null;
social_tiktok: string | null;
social_instagram: string | null;
social_github: string | null;
variants: UserVariant[];
}UserVariant Object
interface UserVariant {
language_id: number;
url: string;
name: string | null;
bio: string | null;
location: string | null;
}Media Object
interface Media {
id: number;
uploaded_at: number;
name: string;
url: string;
original_name: string;
extension: string;
}Navigation Object
interface Navigation {
id: number;
created_at: number;
url: string;
type: NavigationType;
sort: number;
variants: NavigationVariant[];
}NavigationVariant Object
interface NavigationVariant {
language_id: number;
name: string | null;
}Language Object
interface Language {
id: number;
code: string;
name: string;
is_primary: boolean;
}Redirect Object
interface Redirect {
id: number;
created_at: number;
path: string;
to: string;
type: 'temporary' | 'permanent';
}Webhook Object
interface Webhook {
id: number;
url: string;
events: string[];
secret: string;
}Route Object
interface Route {
id: number;
created_at: number;
name: string;
match: string;
template: string;
posts_filter: string | null;
content_type: string | null;
is_enabled: boolean;
}File Object
interface FileObject {
id: number;
name: string;
content: string | null;
folder: 'templates' | 'assets' | 'styles' | 'lang';
}Export Object
interface Export {
id: number;
createdf_at: number;
format: 'hyvor_blogs' | 'wordpress';
status: 'pending' | 'completed' | 'failed';
url: string | null;
error?: string;
}Theme Object
interface Theme {
id: number;
type: 'original' | 'ported';
name: string;
}Link Object
interface LinkObject {
id: number;
url: string;
full_url: string;
status_code: number;
status_type: 'ok' | 'broken' | 'redirect' | 'ignored';
ignored: boolean;
post_id: number;
post_variant_id: number;
post_variant_language_id: number;
post_variant_title: string;
}Check Object
interface CheckObject {
id: number;
created_at: number;
status: 'pending' | 'completed' | 'failed';
error: string | null;
post_count: number;
post_variants_count: number;
page_count: number;
page_variants_count: number;
links_total_count: number;
links_ok_count: number;
links_broken_count: number;
links_redirect_count: number;
links_ignored_count: number;
}