Manage blog posts, articles, and other text-based content. Contents support rich text editing (TipTap), markdown input, categories, tags, SEO metadata, revision history, scheduled publishing, and multi-language translations.
Status workflow: draft → scheduled → published → archived
Content body can be submitted as markdown via bodyMarkdown and is
stored internally as TipTap JSON, then served as HTML to frontends.
18 endpoints
GET /contents
List contents
Returns a paginated list of contents for your site. Supports filtering by status, category, tag, locale, date range, and full-text search.
Results include content summaries (no body) for performance. Use
GET /contents/{id} to retrieve the full body.
Parameters
Name | In | Type | Required | Description |
|---|---|---|---|---|
| query | number | No | Number |
| query | number | No | Number <= 100 |
| query | string | No | Resource type |
| query | "draft" | "published" | "archived" | "scheduled" | No | One of: draft, published, archived, scheduled |
| query | "standard" | "structured" | No | One of: standard, structured |
| query | "created_at" | "updated_at" | "published_at" | "title" | "slug" | No | One of: created_at, updated_at, published_at, title, slug |
| query | "asc" | "desc" | No | One of: asc, desc |
| query | string[] | No | Array of strings |
| query | string[] | No | Array of strings |
| query | string | No | Author user ID |
| query | string | No | Filter from date (ISO 8601) |
| query | string | No | Filter until date (ISO 8601) |
| query | string | No | Filter by publish date from (ISO 8601) |
| query | string | No | Filter by publish date until (ISO 8601) |
| query | string | No | URL-friendly identifier, unique per site and locale |
| query | string[] | No | Array of strings |
| query | string[] | No | Array of strings |
| query | string[] | No | Array of strings |
| query | boolean | No | Boolean |
| query | boolean | No | Boolean |
| query | string | No | BCP 47 locale code (e.g. "en", "fr") |
| query | string | No | Translation group UUID (links translations across locales) |
| query | boolean | No | Boolean |
Responses
Status | Description |
|---|---|
| Successful response |
| Unauthorized — invalid or missing API token |
| Forbidden — insufficient permissions |
Examples
# List published articles, page 1
curl "https://api.lynkow.com/v1/contents?status=published&page=1&limit=10" \
-H "Authorization: Bearer $API_TOKEN"Lynkow SDK (server-side)
// The SDK's public API only fetches published content.
// Use the V1 API directly for draft/archived access.
const response = await fetch('https://api.lynkow.com/v1/contents?status=draft', {
headers: { Authorization: `Bearer ${apiToken}` }
})Response Example
{
"data": [
{
"id": 42,
"title": "Getting Started with Lynkow",
"slug": "getting-started-with-lynkow",
"type": "post",
"status": "published",
"excerpt": "Learn how to set up your first headless CMS with Lynkow.",
"locale": "en",
"featuredImage": {
"url": "https://cdn.lynkow.com/sites/abc123/hero.jpg",
"alt": "Lynkow dashboard screenshot"
},
"categories": [
{
"id": 1,
"name": "Tutorials",
"slug": "tutorials"
}
],
"tags": [
{
"id": 5,
"name": "Getting Started",
"slug": "getting-started"
}
],
"author": {
"id": 1,
"fullName": "Jane Doe"
},
"publishedAt": "2025-03-15T10:30:00.000Z",
"createdAt": "2025-03-14T08:00:00.000Z",
"updatedAt": "2025-03-15T10:30:00.000Z"
}
],
"meta": {
"total": 42,
"perPage": 15,
"currentPage": 1,
"lastPage": 3
}
}POST /contents
Create a content
Creates a new content in draft status by default. You must provide
at least a title and type (currently only "post" is supported).
The slug is auto-generated from the title if not provided. If a
slug collision occurs, a numeric suffix is appended (e.g., my-post-2).
Submit the body as markdown via bodyMarkdown. The API converts it
to TipTap JSON internally. Alternatively, submit raw TipTap JSON via
body for advanced formatting control.
Request Body
Content-Type: application/json
Field | Type | Required | Description |
|---|---|---|---|
| "post" | Yes | Required. Resource type. One of: post |
| string | Yes | Required. Display title. 1-500 characters |
| string | Yes | Required. URL-friendly identifier, unique per site and locale. 1-500 characters |
| string | No | Short summary for previews |
| object | No | Rich text content as TipTap JSON |
| string | No | Content as Markdown (converted to TipTap JSON on save) |
| "draft" | "published" | "archived" | "scheduled" | No | One of: draft, published, archived, scheduled |
| string | No | Featured image URL |
| string | No | Scheduled publication datetime (ISO 8601) |
| string | No | Custom meta title for SEO. Max 255 characters |
| string | No | Meta description for search engines. Max 500 characters |
| string | No | Comma-separated SEO keywords. Max 500 characters |
| string | No | Canonical URL override. Max 1000 characters |
| string | No | Open Graph image URL for social sharing. Max 1000 characters |
| object | No | Additional metadata |
| string[] | No | Min 1 character. Array of strings |
| string[] | No | Array of strings |
| object | null | No | Custom fields data (structured content) |
| string | No | BCP 47 locale code (e.g. "en", "fr") |
| string | No | Translation group UUID (links translations across locales) |
| object | No | FAQ detection and JSON-LD settings |
Responses
Status | Description |
|---|---|
| Successful response |
| Unauthorized — invalid or missing API token |
| Forbidden — insufficient permissions |
| Validation error |
Notes: -
scheduledAtis required whenstatusis"scheduled"and must be in the future.
categoryIdsmust reference existing category UUIDs for the same site.
customDatais available only for contents whose category uses structured content schemas.
Examples
curl -X POST https://api.lynkow.com/v1/contents \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "post",
"title": "Getting Started with Lynkow",
"bodyMarkdown": "# Welcome\n\nThis is your first article.",
"status": "draft",
"categoryIds": ["uuid-of-category"]
}'Response Example
{
"data": {
"id": 43,
"title": "Getting Started with Lynkow",
"slug": "getting-started-with-lynkow",
"type": "post",
"status": "draft",
"excerpt": null,
"bodyHtml": "<h1>Welcome</h1><p>This is your first article.</p>",
"locale": "en",
"featuredImage": null,
"categories": [
{
"id": 1,
"name": "Tutorials",
"slug": "tutorials"
}
],
"tags": [],
"meta": {
"metaTitle": null,
"metaDescription": null,
"canonicalUrl": null,
"ogImage": null
},
"author": {
"id": 1,
"fullName": "Jane Doe"
},
"publishedAt": null,
"createdAt": "2025-04-06T12:00:00.000Z",
"updatedAt": "2025-04-06T12:00:00.000Z"
}
}GET /contents/search
Search contents
Full-text search across content titles, slugs, and bodies. Returns matching contents with highlighted search terms.
More powerful than the search query param on the list endpoint —
this performs full-text search with ranking.
Parameters
Name | In | Type | Required | Description |
|---|---|---|---|---|
| query | number | No | Number |
| query | number | No | Number <= 100 |
| query | string | No | Resource type |
| query | "draft" | "published" | "archived" | "scheduled" | No | One of: draft, published, archived, scheduled |
| query | "standard" | "structured" | No | One of: standard, structured |
| query | "created_at" | "updated_at" | "published_at" | "title" | "slug" | No | One of: created_at, updated_at, published_at, title, slug |
| query | "asc" | "desc" | No | One of: asc, desc |
| query | string[] | No | Array of strings |
| query | string[] | No | Array of strings |
| query | string | No | Author user ID |
| query | string | No | Filter from date (ISO 8601) |
| query | string | No | Filter until date (ISO 8601) |
| query | string | No | Filter by publish date from (ISO 8601) |
| query | string | No | Filter by publish date until (ISO 8601) |
| query | string | No | URL-friendly identifier, unique per site and locale |
| query | string[] | No | Array of strings |
| query | string[] | No | Array of strings |
| query | string[] | No | Array of strings |
| query | boolean | No | Boolean |
| query | boolean | No | Boolean |
| query | string | No | BCP 47 locale code (e.g. "en", "fr") |
| query | string | No | Translation group UUID (links translations across locales) |
| query | boolean | No | Boolean |
Responses
Status | Description |
|---|---|
| Successful response |
| Unauthorized — invalid or missing API token |
| Forbidden — insufficient permissions |
Examples
curl "https://api.lynkow.com/v1/contents/search?q=getting+started&status=published" \
-H "Authorization: Bearer $API_TOKEN"Response Example
{
"data": [
{
"id": 42,
"title": "Getting Started with Lynkow",
"slug": "getting-started-with-lynkow",
"type": "post",
"status": "published",
"excerpt": "Learn how to set up your first headless CMS with Lynkow.",
"locale": "en",
"categories": [
{
"id": 1,
"name": "Tutorials",
"slug": "tutorials"
}
],
"tags": [
{
"id": 5,
"name": "Getting Started",
"slug": "getting-started"
}
],
"author": {
"id": 1,
"fullName": "Jane Doe"
},
"publishedAt": "2025-03-15T10:30:00.000Z",
"createdAt": "2025-03-14T08:00:00.000Z",
"updatedAt": "2025-03-15T10:30:00.000Z"
}
],
"meta": {
"total": 3,
"perPage": 15,
"currentPage": 1,
"lastPage": 1
}
}POST /contents/bulk/publish
Bulk publish contents
Publishes multiple contents at once. Provide an array of content IDs.
Contents must be in draft or scheduled status. Already published
contents are silently skipped.
Request Body
Content-Type: application/json
Field | Type | Required | Description |
|---|---|---|---|
| string[] | Yes | Required. 1-100 characters. Array of strings |
Responses
Status | Description |
|---|---|
| Successful response |
| Unauthorized — invalid or missing API token |
| Forbidden — insufficient permissions |
| Validation error |
Notes: - Maximum 50 IDs per request.
Triggers
content.publishedwebhook for each content.
Examples
curl -X POST https://api.lynkow.com/v1/contents/bulk/publish \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"ids": [42, 43, 44, 45, 46]}'Response Example
{
"published": 5
}POST /contents/bulk/archive
Bulk archive contents
Archives multiple published contents at once. Archived contents are hidden from the public API but preserved for future reference.
Request Body
Content-Type: application/json
Field | Type | Required | Description |
|---|---|---|---|
| string[] | Yes | Required. 1-100 characters. Array of strings |
Responses
Status | Description |
|---|---|
| Successful response |
| Unauthorized — invalid or missing API token |
| Forbidden — insufficient permissions |
| Validation error |
Notes: - Maximum 50 IDs per request.
Triggers
content.archivedwebhook for each content.
Examples
curl -X POST https://api.lynkow.com/v1/contents/bulk/archive \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"ids": [42, 43, 44]}'Response Example
{
"archived": 3
}POST /contents/bulk/delete
Bulk delete contents
Permanently deletes multiple contents. This action is irreversible.
Request Body
Content-Type: application/json
Field | Type | Required | Description |
|---|---|---|---|
| string[] | Yes | Required. 1-100 characters. Array of strings |
Responses
Status | Description |
|---|---|
| Successful response |
| Unauthorized — invalid or missing API token |
| Forbidden — insufficient permissions |
| Validation error |
Notes: - Maximum 50 IDs per request.
Associated revisions, translations, and category/tag associations are also deleted.
Examples
curl -X POST https://api.lynkow.com/v1/contents/bulk/delete \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"ids": [50, 51]}'Response Example
{
"deleted": 2
}GET /contents/slug/:slug
Get content by slug
Retrieves a single content by its URL slug. Useful when you know the slug but not the numeric ID (e.g., from a URL path).
Returns the full content including HTML body, categories, tags, SEO metadata, and structured data.
Parameters
Name | In | Type | Required | Description |
|---|---|---|---|---|
| path | string | Yes | URL-friendly identifier, unique per site and locale |
Responses
Status | Description |
|---|---|
| Successful response |
| Unauthorized — invalid or missing API token |
| Forbidden — insufficient permissions |
| Not found |
Examples
curl https://api.lynkow.com/v1/contents/slug/getting-started-with-lynkow \
-H "Authorization: Bearer $API_TOKEN"Response Example
{
"data": {
"id": 42,
"title": "Getting Started with Lynkow",
"slug": "getting-started-with-lynkow",
"type": "post",
"status": "published",
"excerpt": "Learn how to set up your first headless CMS.",
"bodyHtml": "<h1>Welcome</h1><p>This is your first article...</p>",
"locale": "en",
"featuredImage": {
"url": "https://cdn.lynkow.com/sites/abc123/hero.jpg",
"alt": "Lynkow dashboard screenshot"
},
"categories": [
{
"id": 1,
"name": "Tutorials",
"slug": "tutorials"
}
],
"tags": [
{
"id": 5,
"name": "Getting Started",
"slug": "getting-started"
}
],
"meta": {
"metaTitle": "Getting Started with Lynkow | My Blog",
"metaDescription": "A step-by-step guide to setting up Lynkow.",
"canonicalUrl": null,
"ogImage": null
},
"author": {
"id": 1,
"fullName": "Jane Doe"
},
"publishedAt": "2025-03-15T10:30:00.000Z",
"createdAt": "2025-03-14T08:00:00.000Z",
"updatedAt": "2025-03-15T10:30:00.000Z"
}
}GET /contents/:id
Get a content
Retrieves a single content by its numeric ID. Returns the full object including HTML body, categories, tags, SEO metadata, structured data (FAQ, Article JSON-LD), and featured image with CDN variants.
Parameters
Name | In | Type | Required | Description |
|---|---|---|---|---|
| path | string | Yes | Unique identifier |
Responses
Status | Description |
|---|---|
| Successful response |
| Unauthorized — invalid or missing API token |
| Forbidden — insufficient permissions |
| Not found |
Examples
curl https://api.lynkow.com/v1/contents/42 \
-H "Authorization: Bearer $API_TOKEN"Response Example
{
"id": 42,
"title": "Getting Started with Lynkow",
"slug": "getting-started-with-lynkow",
"type": "post",
"status": "published",
"excerpt": "Learn how to set up your first headless CMS.",
"bodyHtml": "<h1>Welcome</h1><p>This is your first article...</p>",
"locale": "en",
"featuredImage": {
"url": "https://cdn.lynkow.com/sites/abc123/hero.jpg",
"alt": "Lynkow dashboard screenshot",
"variants": {
"thumbnail": "https://cdn.lynkow.com/sites/abc123/hero.jpg?w=150",
"card": "https://cdn.lynkow.com/sites/abc123/hero.jpg?w=400",
"content": "https://cdn.lynkow.com/sites/abc123/hero.jpg?w=800",
"medium": "https://cdn.lynkow.com/sites/abc123/hero.jpg?w=1200"
}
},
"categories": [
{
"id": 1,
"name": "Tutorials",
"slug": "tutorials"
}
],
"tags": [
{
"id": 5,
"name": "Getting Started",
"slug": "getting-started"
}
],
"meta": {
"metaTitle": "Getting Started with Lynkow | My Blog",
"metaDescription": "A step-by-step guide to setting up Lynkow.",
"canonicalUrl": null,
"ogImage": null
},
"author": {
"id": 1,
"fullName": "Jane Doe"
},
"publishedAt": "2025-03-15T10:30:00.000Z",
"createdAt": "2025-03-14T08:00:00.000Z",
"updatedAt": "2025-03-15T10:30:00.000Z",
"alternates": [
{
"locale": "fr",
"id": 43,
"slug": "premiers-pas-avec-lynkow"
}
]
}PUT /contents/:id
Update a content
Updates an existing content. Only the fields you include in the request body are modified — omitted fields remain unchanged.
Updating a published content does not unpublish it. To change status, use the dedicated publish/archive endpoints.
Parameters
Name | In | Type | Required | Description |
|---|---|---|---|---|
| path | string | Yes | Unique identifier |
Request Body
Content-Type: application/json
Field | Type | Required | Description |
|---|---|---|---|
| "post" | No | Resource type. One of: post |
| string | No | Display title. 1-500 characters |
| string | No | URL-friendly identifier, unique per site and locale. 1-500 characters |
| string | No | Short summary for previews |
| object | No | Rich text content as TipTap JSON |
| string | No | Content as Markdown (converted to TipTap JSON on save) |
| "draft" | "published" | "archived" | "scheduled" | No | One of: draft, published, archived, scheduled |
| string | No | Featured image URL |
| string | No | Scheduled publication datetime (ISO 8601) |
| string | No | Custom meta title for SEO. Max 255 characters |
| string | No | Meta description for search engines. Max 500 characters |
| string | No | Comma-separated SEO keywords. Max 500 characters |
| string | No | Canonical URL override. Max 1000 characters |
| string | No | Open Graph image URL for social sharing. Max 1000 characters |
| object | No | Additional metadata |
| string[] | No | Min 1 character. Array of strings |
| string[] | No | Array of strings |
| object | null | No | Custom fields data (structured content) |
| object | No | FAQ detection and JSON-LD settings |
Responses
Status | Description |
|---|---|
| Successful response |
| Unauthorized — invalid or missing API token |
| Forbidden — insufficient permissions |
| Not found |
| Validation error |
Notes: - Creates a new revision automatically. Use
GET /contents/{id}/revisionsto view history.
Changing the
slugdoes not create a redirect — manage redirects separately.
Examples
curl -X PUT https://api.lynkow.com/v1/contents/42 \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Updated Title",
"excerpt": "Updated excerpt for the article."
}'Response Example
{
"data": {
"id": 42,
"title": "Updated Title",
"slug": "getting-started-with-lynkow",
"type": "post",
"status": "published",
"excerpt": "Updated excerpt for the article.",
"bodyHtml": "<h1>Welcome</h1><p>This is your first article...</p>",
"locale": "en",
"categories": [
{
"id": 1,
"name": "Tutorials",
"slug": "tutorials"
}
],
"tags": [
{
"id": 5,
"name": "Getting Started",
"slug": "getting-started"
}
],
"author": {
"id": 1,
"fullName": "Jane Doe"
},
"publishedAt": "2025-03-15T10:30:00.000Z",
"createdAt": "2025-03-14T08:00:00.000Z",
"updatedAt": "2025-04-06T14:00:00.000Z"
}
}DELETE /contents/:id
Delete a content
Permanently deletes a content and all its revisions. This action is irreversible. Consider archiving instead if you may need the content later.
Parameters
Name | In | Type | Required | Description |
|---|---|---|---|---|
| path | string | Yes | Unique identifier |
Responses
Status | Description |
|---|---|
| Successful response |
| Unauthorized — invalid or missing API token |
| Forbidden — insufficient permissions |
| Not found |
Notes: - Triggers
content.deletedwebhook.
Associated category/tag links are removed.
Examples
curl -X DELETE https://api.lynkow.com/v1/contents/42 \
-H "Authorization: Bearer $API_TOKEN"Response Example
{
"message": "Content deleted"
}POST /contents/:id/publish
Publish a content
Transitions a content from draft or scheduled to published.
Sets publishedAt to the current timestamp if not already set.
Parameters
Name | In | Type | Required | Description |
|---|---|---|---|---|
| path | string | Yes | Unique identifier |
Responses
Status | Description |
|---|---|
| Successful response |
| Unauthorized — invalid or missing API token |
| Forbidden — insufficient permissions |
| Not found |
| Validation error |
Notes: - Triggers
content.publishedwebhook.
Triggers IndexNow submission if configured.
Cannot publish an already archived content — restore it to draft first.
Examples
curl -X POST https://api.lynkow.com/v1/contents/42/publish \
-H "Authorization: Bearer $API_TOKEN"Response Example
{
"data": {
"id": 42,
"title": "Getting Started with Lynkow",
"slug": "getting-started-with-lynkow",
"type": "post",
"status": "published",
"excerpt": "Learn how to set up your first headless CMS.",
"locale": "en",
"publishedAt": "2025-04-06T14:30:00.000Z",
"createdAt": "2025-03-14T08:00:00.000Z",
"updatedAt": "2025-04-06T14:30:00.000Z"
}
}GET /contents/:id/revisions
List content revisions
Returns the version history for a content, ordered by most recent first. Each revision captures the full state of the content at that point in time.
Revisions are created automatically on every update via the API or admin dashboard.
Parameters
Name | In | Type | Required | Description |
|---|---|---|---|---|
| path | string | Yes | Unique identifier |
Responses
Status | Description |
|---|---|
| Successful response |
| Unauthorized — invalid or missing API token |
| Forbidden — insufficient permissions |
| Not found |
Examples
curl https://api.lynkow.com/v1/contents/42/revisions \
-H "Authorization: Bearer $API_TOKEN"Response Example
{
"data": [
{
"id": 301,
"contentId": 42,
"title": "Updated Title",
"changes": [
{
"field": "title",
"from": "Getting Started with Lynkow",
"to": "Updated Title"
},
{
"field": "excerpt",
"from": null,
"to": "Updated excerpt for the article."
}
],
"createdAt": "2025-04-06T14:00:00.000Z",
"author": {
"id": 1,
"fullName": "Jane Doe"
}
},
{
"id": 300,
"contentId": 42,
"title": "Getting Started with Lynkow",
"changes": [
{
"field": "bodyMarkdown",
"from": "# Welcome",
"to": "# Welcome\n\nThis is your first article."
}
],
"createdAt": "2025-03-15T10:30:00.000Z",
"author": {
"id": 1,
"fullName": "Jane Doe"
}
}
]
}POST /contents/:id/revisions/:revisionId/restore
Restore a content revision
Restores a content to a previous revision. The current state is saved as a new revision before restoring, so no data is lost.
Parameters
Name | In | Type | Required | Description |
|---|---|---|---|---|
| path | string | Yes | Unique identifier |
| path | string | Yes | Revision ID |
Responses
Status | Description |
|---|---|
| Successful response |
| Unauthorized — invalid or missing API token |
| Forbidden — insufficient permissions |
| Not found |
| Validation error |
Examples
curl -X POST https://api.lynkow.com/v1/contents/42/revisions/300/restore \
-H "Authorization: Bearer $API_TOKEN"Response Example
{
"data": {
"id": 42,
"title": "Getting Started with Lynkow",
"slug": "getting-started-with-lynkow",
"type": "post",
"status": "published",
"excerpt": "Learn how to set up your first headless CMS.",
"bodyHtml": "<h1>Welcome</h1><p>Original content restored.</p>",
"locale": "en",
"createdAt": "2025-03-14T08:00:00.000Z",
"updatedAt": "2025-04-06T15:00:00.000Z"
}
}GET /contents/:id/revisions/:revisionAId/compare/:revisionBId
Compare two revisions
Returns a diff between two revisions of the same content. Useful for reviewing what changed between versions.
Parameters
Name | In | Type | Required | Description |
|---|---|---|---|---|
| path | string | Yes | Unique identifier |
| path | string | Yes | First revision ID (for comparison) |
| path | string | Yes | Second revision ID (for comparison) |
Responses
Status | Description |
|---|---|
| Successful response |
| Unauthorized — invalid or missing API token |
| Forbidden — insufficient permissions |
| Not found |
Examples
curl https://api.lynkow.com/v1/contents/42/revisions/300/compare/301 \
-H "Authorization: Bearer $API_TOKEN"Response Example
{
"changes": {
"title": {
"before": "Getting Started with Lynkow",
"after": "Updated Title"
},
"excerpt": {
"before": null,
"after": "Updated excerpt for the article."
}
}
}POST /contents/:id/duplicate
Duplicate a content
Creates a copy of an existing content with a new auto-generated slug
(suffixed with -copy). The duplicate is created in draft status
regardless of the original's status.
Parameters
Name | In | Type | Required | Description |
|---|---|---|---|---|
| path | string | Yes | Unique identifier |
Responses
Status | Description |
|---|---|
| Successful response |
| Unauthorized — invalid or missing API token |
| Forbidden — insufficient permissions |
| Not found |
| Validation error |
Notes: - Category and tag associations are copied.
Revisions are NOT copied — the duplicate starts with a clean history.
Examples
curl -X POST https://api.lynkow.com/v1/contents/42/duplicate \
-H "Authorization: Bearer $API_TOKEN"Response Example
{
"data": {
"id": 44,
"title": "Getting Started with Lynkow",
"slug": "getting-started-with-lynkow-copy",
"type": "post",
"status": "draft",
"excerpt": "Learn how to set up your first headless CMS.",
"locale": "en",
"categories": [
{
"id": 1,
"name": "Tutorials",
"slug": "tutorials"
}
],
"tags": [
{
"id": 5,
"name": "Getting Started",
"slug": "getting-started"
}
],
"publishedAt": null,
"createdAt": "2025-04-06T15:00:00.000Z",
"updatedAt": "2025-04-06T15:00:00.000Z"
}
}GET /contents/:id/translations
Get translation status
Returns the translation status for a content across all enabled locales. For each locale, indicates whether a translation exists and its current status.
Parameters
Name | In | Type | Required | Description |
|---|---|---|---|---|
| path | string | Yes | Unique identifier |
Responses
Status | Description |
|---|---|
| Successful response |
| Unauthorized — invalid or missing API token |
| Forbidden — insufficient permissions |
| Not found |
Examples
curl https://api.lynkow.com/v1/contents/42/translations \
-H "Authorization: Bearer $API_TOKEN"Response Example
{
"data": {
"en": {
"status": "complete",
"contentId": 42,
"title": "Getting Started with Lynkow"
},
"fr": {
"status": "complete",
"contentId": 43,
"title": "Premiers pas avec Lynkow"
},
"es": {
"status": "missing",
"contentId": null,
"title": null
},
"de": {
"status": "missing",
"contentId": null,
"title": null
}
}
}GET /contents/:id/alternates
Get alternate locale versions
Returns links to all translated versions of this content. Useful for
building hreflang tags or locale switchers on the frontend.
Parameters
Name | In | Type | Required | Description |
|---|---|---|---|---|
| path | string | Yes | Unique identifier |
Responses
Status | Description |
|---|---|
| Successful response |
| Unauthorized — invalid or missing API token |
| Forbidden — insufficient permissions |
| Not found |
Examples
curl https://api.lynkow.com/v1/contents/42/alternates \
-H "Authorization: Bearer $API_TOKEN"Response Example
{
"data": [
{
"locale": "en",
"id": 42,
"slug": "getting-started-with-lynkow",
"path": "/blog/getting-started-with-lynkow"
},
{
"locale": "fr",
"id": 43,
"slug": "premiers-pas-avec-lynkow",
"path": "/fr/blog/premiers-pas-avec-lynkow"
}
]
}POST /contents/:id/copy-to-locale
Copy content to another locale
Creates a translated copy of a content in a target locale. The copy
is linked to the original via a translationGroupId, enabling
locale-aware navigation.
Parameters
Name | In | Type | Required | Description |
|---|---|---|---|---|
| path | string | Yes | Unique identifier |
Request Body
Content-Type: application/json
Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | Required |
Responses
Status | Description |
|---|---|
| Successful response |
| Unauthorized — invalid or missing API token |
| Forbidden — insufficient permissions |
| Not found |
| Validation error |
Notes: - Requires
localein the request body (e.g.,"fr","es").
The content body and metadata are copied as-is — translation is manual.
Fails if a translation already exists for that locale.
Examples
curl -X POST https://api.lynkow.com/v1/contents/42/copy-to-locale \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"locale": "fr"}'Response Example
{
"data": {
"id": 99,
"title": "Getting Started with Lynkow",
"slug": "getting-started-with-lynkow",
"type": "post",
"status": "draft",
"locale": "fr",
"translationGroupId": "tg-uuid-1",
"createdAt": "2025-04-06T15:00:00.000Z",
"updatedAt": "2025-04-06T15:00:00.000Z"
}
}