diff --git a/docs/.vitepress/components/AposApiExplorer.vue b/docs/.vitepress/components/AposApiExplorer.vue
new file mode 100644
index 00000000..253ba72d
--- /dev/null
+++ b/docs/.vitepress/components/AposApiExplorer.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/.vitepress/sidebarGuide.js b/docs/.vitepress/sidebarGuide.js
index 430a615d..af5a5a7f 100644
--- a/docs/.vitepress/sidebarGuide.js
+++ b/docs/.vitepress/sidebarGuide.js
@@ -223,7 +223,8 @@ const sidebarGuide = [
icon: 'brain-circuit',
text: 'REST API Reference',
collapsed: true,
- items: getItemRefs(['README'], '', 'reference', 'api')
+ link: 'reference/api/rest-api-reference.md',
+ items: getItemRefs(['README', 'rest-api-reference'], '', 'reference', 'api')
},
{
icon: 'open-book',
diff --git a/docs/.vitepress/theme/index.js b/docs/.vitepress/theme/index.js
index d7191860..7a6a1358 100644
--- a/docs/.vitepress/theme/index.js
+++ b/docs/.vitepress/theme/index.js
@@ -16,6 +16,7 @@ import { createEventBus } from './eventBus';
import AposTutorialFilter from '../components/AposTutorialFilter.vue';
import { setupUpdateChecker } from '../helpers/updateChecker';
import { setupYouTubeTracking } from '../helpers/youtubeTracking';
+import AposApiExplorer from '../components/AposApiExplorer.vue'
import { setupAnchorFix } from '../helpers/anchorFix';
export const eventBus = createEventBus();
@@ -42,6 +43,7 @@ export default {
app.component('AposTwoColumns', AposTwoColumns);
app.component('AposCtaButton', AposCtaButton);
app.component('AposTutorialFilter', AposTutorialFilter);
+ app.component('AposApiExplorer', AposApiExplorer);
let anchorFixCleanup = null;
diff --git a/docs/.vitepress/theme/styles/index.styl b/docs/.vitepress/theme/styles/index.styl
index b3343130..bb4a2017 100644
--- a/docs/.vitepress/theme/styles/index.styl
+++ b/docs/.vitepress/theme/styles/index.styl
@@ -9,4 +9,5 @@
@import 'sidebar.styl';
@import 'aside.styl';
@import 'youtube.styl';
+@import 'swagger.styl';
@import 'columns.styl';
diff --git a/docs/.vitepress/theme/styles/swagger.styl b/docs/.vitepress/theme/styles/swagger.styl
new file mode 100644
index 00000000..a549b973
--- /dev/null
+++ b/docs/.vitepress/theme/styles/swagger.styl
@@ -0,0 +1,939 @@
+/* Refactored Swagger UI Dark Mode */
+/* Using consistent color palette and better organization */
+
+/* === COLOR VARIABLES === */
+/*
+ Background: #0f0f23 (deep dark), #1a1a2e (dark), #16213e (medium), #2a2a40 (light)
+ Text: #ffffff (primary), #e2e8f0 (secondary), #94a3b8 (muted), #64748b (subtle)
+ Accent: #60a5fa (blue), #34d399 (green), #f59e0b (amber), #ef4444 (red)
+*/
+
+/* === BASE CONTAINER === */
+html.dark #swagger-ui {
+ background-color: #0f0f23;
+ color: #e2e8f0;
+}
+
+/* === TOPBAR === */
+html.dark #swagger-ui .topbar {
+ background-color: #1a1a2e;
+ border-bottom: 1px solid #2a2a40;
+}
+
+/* === OPERATION BLOCKS === */
+html.dark #swagger-ui .opblock {
+ background-color: #1a1a2e;
+ border: 1px solid #2a2a40;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
+}
+
+html.dark #swagger-ui .opblock-summary-method,
+html.dark #swagger-ui .opblock-summary-description,
+html.dark #swagger-ui .opblock-title {
+ color: #ffffff;
+}
+
+html.dark #swagger-ui .opblock-description-wrapper p,
+html.dark #swagger-ui .opblock-description-wrapper h2,
+html.dark #swagger-ui .opblock-description-wrapper h3,
+html.dark #swagger-ui .opblock-description-wrapper h4 {
+ color: #e2e8f0;
+}
+
+html.dark #swagger-ui .opblock-section-header {
+ background-color: #2a2a40;
+ color: #ffffff;
+ border-bottom: 1px solid #374151;
+}
+
+html.dark #swagger-ui .opblock-control-arrow {
+ color: #94a3b8;
+}
+
+html.dark #swagger-ui .opblock-control-arrow svg path {
+ fill: currentColor;
+}
+
+html.dark #swagger-ui .expand-operation {
+ color: #94a3b8;
+}
+
+html.dark #swagger-ui .expand-operation svg path {
+ fill: currentColor;
+}
+
+/* === RESPONSES === */
+html.dark #swagger-ui .responses-inner,
+html.dark #swagger-ui .response-col_description,
+html.dark #swagger-ui .response-col_status,
+html.dark #swagger-ui .response-col_links {
+ background-color: #16213e;
+ color: #e2e8f0;
+}
+
+html.dark #swagger-ui .responses-inner h2,
+html.dark #swagger-ui .responses-inner h3,
+html.dark #swagger-ui .responses-inner h4,
+html.dark #swagger-ui .responses-inner h5,
+html.dark #swagger-ui .responses-inner h6,
+html.dark #swagger-ui .responses-inner p {
+ color: #e2e8f0;
+}
+
+/* === TYPOGRAPHY === */
+html.dark #swagger-ui h1,
+html.dark #swagger-ui h2,
+html.dark #swagger-ui h3,
+html.dark #swagger-ui h4,
+html.dark #swagger-ui h5,
+html.dark #swagger-ui h6 {
+ color: #ffffff;
+}
+
+html.dark #swagger-ui p {
+ color: #e2e8f0;
+}
+
+/* === LINKS === */
+html.dark #swagger-ui a {
+ color: #60a5fa;
+ transition: color 0.2s ease;
+}
+
+html.dark #swagger-ui a:hover {
+ color: #93c5fd;
+}
+
+/* === RENDERED MARKDOWN === */
+html.dark #swagger-ui .renderedMarkdown {
+ color: #e2e8f0;
+}
+
+html.dark #swagger-ui .renderedMarkdown h1,
+html.dark #swagger-ui .renderedMarkdown h2,
+html.dark #swagger-ui .renderedMarkdown h3,
+html.dark #swagger-ui .renderedMarkdown h4,
+html.dark #swagger-ui .renderedMarkdown h5,
+html.dark #swagger-ui .renderedMarkdown h6 {
+ color: #ffffff;
+}
+
+html.dark #swagger-ui .renderedMarkdown a {
+ color: #60a5fa;
+}
+
+html.dark #swagger-ui .renderedMarkdown a:hover {
+ color: #93c5fd;
+}
+
+html.dark #swagger-ui .renderedMarkdown p {
+ color: #e2e8f0;
+}
+
+html.dark #swagger-ui .renderedMarkdown code {
+ background-color: #2a2a40;
+ color: #fbbf24;
+ padding: 2px 4px;
+ border-radius: 3px;
+}
+
+html.dark #swagger-ui .renderedMarkdown li,
+html.dark #swagger-ui .renderedMarkdown ul,
+html.dark #swagger-ui .renderedMarkdown ol,
+html.dark #swagger-ui li,
+html.dark #swagger-ui ul,
+html.dark #swagger-ui ol {
+ color: #e2e8f0;
+}
+
+/* === TABLES === */
+html.dark #swagger-ui table {
+ background-color: #1a1a2e;
+ border: 1px solid #2a2a40;
+}
+
+html.dark #swagger-ui table thead tr th,
+html.dark #swagger-ui table.headers td {
+ color: #ffffff;
+ background-color: #2a2a40;
+ border-bottom: 1px solid #374151;
+}
+
+html.dark #swagger-ui table tbody tr {
+ border-bottom: 1px solid #2a2a40;
+}
+
+html.dark #swagger-ui table tbody tr:hover {
+ background-color: rgba(42, 42, 64, 0.3);
+}
+
+/* === PARAMETERS === */
+html.dark #swagger-ui td .parameter__name,
+html.dark #swagger-ui td .parameter__type,
+html.dark #swagger-ui td .parameter__in {
+ color: #e2e8f0;
+}
+
+html.dark #swagger-ui .parameter__name.required:after {
+ color: #ef4444;
+}
+
+/* === EXAMPLES === */
+html.dark #swagger-ui .examples-select__section-label {
+ color: #94a3b8;
+}
+
+html.dark #swagger-ui .example__title {
+ color: #ffffff;
+}
+
+/* === FORM CONTROLS === */
+html.dark #swagger-ui input[type="text"],
+html.dark #swagger-ui input[type="number"],
+html.dark #swagger-ui textarea,
+html.dark #swagger-ui select {
+ background-color: #1a1a2e;
+ color: #e2e8f0;
+ border: 1px solid #2a2a40;
+ border-radius: 4px;
+}
+
+/* Fix for select dropdown arrows */
+html.dark #swagger-ui select {
+ /* Remove default arrow */
+ appearance: none;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+
+ /* Add custom arrow using properly encoded SVG */
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23e2e8f0' d='M6 8L2 4h8z'/%3E%3C/svg%3E");
+ background-repeat: no-repeat;
+ background-position: right 8px center;
+ background-size: 12px;
+ padding-right: 32px;
+}
+
+/* Specific targeting for server dropdown */
+html.dark #swagger-ui .scheme-container select,
+html.dark #swagger-ui .servers select,
+html.dark #swagger-ui .servers-title + select,
+html.dark #swagger-ui [class*="server"] select {
+ appearance: none !important;
+ -webkit-appearance: none !important;
+ -moz-appearance: none !important;
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23e2e8f0' d='M6 8L2 4h8z'/%3E%3C/svg%3E") !important;
+ background-repeat: no-repeat !important;
+ background-position: right 8px center !important;
+ background-size: 12px !important;
+ padding-right: 32px !important;
+}
+
+html.dark #swagger-ui input[type="text"]:focus,
+html.dark #swagger-ui input[type="number"]:focus,
+html.dark #swagger-ui textarea:focus,
+html.dark #swagger-ui select:focus {
+ border-color: #60a5fa;
+ box-shadow: 0 0 0 2px rgba(96, 165, 250, 0.2);
+ outline: none;
+}
+
+html.dark #swagger-ui input[type="text"]:disabled,
+html.dark #swagger-ui input[type="number"]:disabled,
+html.dark #swagger-ui textarea:disabled {
+ background-color: #16213e;
+ color: #64748b;
+ cursor: not-allowed;
+}
+
+/* === BUTTONS === */
+html.dark #swagger-ui .try-out__btn {
+ background-color: #60a5fa;
+ color: #ffffff;
+ border: none;
+ border-radius: 4px;
+ transition: background-color 0.2s ease;
+}
+
+html.dark #swagger-ui .try-out__btn:hover {
+ background-color: #3b82f6;
+}
+
+html.dark #swagger-ui .authorization__btn {
+ color: #94a3b8;
+ background-color: transparent;
+ border: 1px solid #2a2a40;
+}
+
+html.dark #swagger-ui .authorization__btn:hover {
+ color: #60a5fa;
+ border-color: #60a5fa;
+}
+
+html.dark #swagger-ui .authorization__btn svg path {
+ fill: currentColor !important;
+}
+
+/* === SCHEME CONTAINER === */
+html.dark #swagger-ui .scheme-container {
+ background-color: #1a1a2e;
+ border: 1px solid #2a2a40;
+}
+
+html.dark #swagger-ui .servers-title {
+ color: #ffffff;
+}
+
+/* === MODELS SECTION === */
+html.dark #swagger-ui .model-box {
+ background-color: #1a1a2e;
+ color: #e2e8f0;
+ border: 1px solid #2a2a40;
+ border-radius: 6px;
+}
+
+html.dark #swagger-ui .model-box .arrow svg path {
+ fill: #94a3b8;
+}
+
+/* Model title and text sizing */
+html.dark #swagger-ui .model-title,
+html.dark #swagger-ui .model-title__text {
+ color: #ffffff;
+ font-weight: 700;
+ font-size: 18px; /* Increased from 14px for better readability */
+ line-height: 1.4;
+}
+
+/* Model box control button */
+html.dark #swagger-ui .model-box-control {
+ background: none;
+ border: none;
+ color: inherit;
+ font-family: inherit;
+ display: flex;
+ align-items: center;
+ width: 100%;
+ text-align: left;
+ cursor: pointer;
+ gap: 6px; /* Add consistent spacing between elements */
+}
+
+/* Collapsed state ellipsis [...] */
+html.dark #swagger-ui .model-box-control span:last-child,
+html.dark #swagger-ui .model button span:last-child {
+ color: #94a3b8;
+ font-size: 18px; /* Match the title size */
+ margin-left: 0; /* Remove margin since we're using gap */
+}
+
+/* Better toggle arrow alignment */
+html.dark #swagger-ui .model-toggle {
+ font-size: 10px;
+ position: relative;
+ top: 0; /* Reset top positioning */
+ display: inline-flex; /* Use inline-flex for better alignment */
+ align-items: center;
+ margin: 0; /* Reset margin */
+ cursor: pointer;
+ transition: transform 0.15s ease-in;
+ transform: rotate(90deg);
+ transform-origin: center;
+}
+
+html.dark #swagger-ui .property {
+ color: #e2e8f0;
+}
+
+html.dark #swagger-ui .prop-type {
+ color: #a78bfa;
+ font-weight: 500;
+}
+
+html.dark #swagger-ui .prop-format {
+ color: #fbbf24;
+}
+
+html.dark #swagger-ui .prop-name {
+ color: #ffffff;
+ font-weight: 500;
+}
+
+html.dark #swagger-ui .prop-enum {
+ color: #34d399;
+}
+
+/* === ENHANCED MODELS SECTION === */
+html.dark #swagger-ui .model {
+ font-size: 12px;
+ font-weight: 300;
+ color: #e2e8f0;
+}
+
+html.dark #swagger-ui .model .deprecated span,
+html.dark #swagger-ui .model .deprecated td {
+ color: #64748b !important;
+}
+
+html.dark #swagger-ui .model .deprecated > td:first-of-type {
+ text-decoration: line-through;
+}
+
+html.dark #swagger-ui .model-toggle {
+ font-size: 10px;
+ position: relative;
+ top: 6px;
+ display: inline-block;
+ margin: auto 0.3em;
+ cursor: pointer;
+ transition: transform 0.15s ease-in;
+ transform: rotate(90deg);
+ transform-origin: 50% 50%;
+}
+
+html.dark #swagger-ui .model-toggle.collapsed {
+ transform: rotate(0deg);
+}
+
+html.dark #swagger-ui .model-toggle:after {
+ display: block;
+ width: 20px;
+ height: 20px;
+ content: "";
+ background: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='%23e2e8f0' d='M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z'/%3E%3C/svg%3E") center no-repeat;
+ background-size: 100%;
+}
+
+html.dark #swagger-ui .model-jump-to-path {
+ position: relative;
+ cursor: pointer;
+}
+
+html.dark #swagger-ui .model-jump-to-path .view-line-link {
+ position: absolute;
+ top: -0.4em;
+ cursor: pointer;
+ color: #60a5fa;
+}
+
+html.dark #swagger-ui .model-jump-to-path .view-line-link:hover {
+ color: #93c5fd;
+}
+
+html.dark #swagger-ui .model-title {
+ position: relative;
+ color: #ffffff;
+}
+
+html.dark #swagger-ui .model-title:hover .model-hint {
+ display: block;
+}
+
+html.dark #swagger-ui .model-hint {
+ position: absolute;
+ top: -1.8em;
+ display: none;
+ padding: 0.1em 0.5em;
+ white-space: nowrap;
+ color: #ffffff;
+ border-radius: 4px;
+ background: rgba(26, 26, 46, 0.95);
+ border: 1px solid #2a2a40;
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3);
+}
+
+html.dark #swagger-ui .model p {
+ margin: 0 0 1em 0;
+ color: #e2e8f0;
+}
+
+html.dark #swagger-ui .model .property {
+ color: #94a3b8;
+ font-style: italic;
+}
+
+html.dark #swagger-ui .model .property.primitive {
+ color: #64748b;
+}
+
+html.dark #swagger-ui .model .property.primitive.extension {
+ display: block;
+}
+
+html.dark #swagger-ui .model .property.primitive.extension > td:first-child {
+ padding-left: 0;
+ padding-right: 0;
+ width: auto;
+}
+
+html.dark #swagger-ui .model .property.primitive.extension > td:first-child:after {
+ content: ":\00a0";
+}
+
+html.dark #swagger-ui .model .external-docs {
+ color: #94a3b8;
+ font-weight: normal;
+}
+
+html.dark #swagger-ui table.model {
+ background: #1a1a2e;
+ border: 1px solid #2a2a40;
+ border-radius: 6px;
+}
+
+html.dark #swagger-ui table.model tr {
+ border-bottom: 1px solid #2a2a40;
+}
+
+html.dark #swagger-ui table.model tr:last-child {
+ border-bottom: none;
+}
+
+html.dark #swagger-ui table.model tr.description {
+ color: #94a3b8;
+ font-weight: normal;
+ background: rgba(15, 15, 35, 0.3);
+}
+
+html.dark #swagger-ui table.model tr.description td:first-child {
+ font-weight: bold;
+ color: #ffffff;
+}
+
+html.dark #swagger-ui table.model tr.property-row:hover {
+ background: rgba(42, 42, 64, 0.3);
+}
+
+html.dark #swagger-ui table.model tr.property-row.required td:first-child {
+ font-weight: bold;
+ color: #ffffff;
+}
+
+html.dark #swagger-ui table.model tr.property-row td {
+ vertical-align: top;
+ padding: 8px 12px;
+ color: #e2e8f0;
+}
+
+html.dark #swagger-ui table.model tr.property-row td:first-child {
+ padding-right: 0.2em;
+}
+
+html.dark #swagger-ui table.model tr.property-row .star {
+ color: #ef4444;
+}
+
+html.dark #swagger-ui table.model tr.extension {
+ color: #94a3b8;
+ background: rgba(15, 15, 35, 0.2);
+}
+
+html.dark #swagger-ui table.model tr.extension td:last-child {
+ vertical-align: top;
+}
+
+html.dark #swagger-ui table.model tr.external-docs {
+ background: rgba(15, 15, 35, 0.2);
+}
+
+html.dark #swagger-ui table.model tr.external-docs td:first-child {
+ font-weight: bold;
+ color: #ffffff;
+}
+
+html.dark #swagger-ui table.model tr .renderedMarkdown {
+ color: #e2e8f0;
+}
+
+html.dark #swagger-ui table.model tr .renderedMarkdown p:first-child {
+ margin-top: 0;
+}
+
+html.dark #swagger-ui section.models {
+ margin: 30px 0;
+ border: 1px solid rgba(42, 42, 64, 0.6);
+ border-radius: 6px;
+ background: #0f0f23;
+}
+
+html.dark #swagger-ui section.models .pointer {
+ cursor: pointer;
+}
+
+html.dark #swagger-ui section.models.is-open {
+ padding: 0 0 20px;
+}
+
+html.dark #swagger-ui section.models.is-open h4 {
+ margin: 0 0 5px 0;
+ border-bottom: 1px solid rgba(52, 52, 80, 0.5);
+}
+
+html.dark #swagger-ui section.models h4 {
+ font-size: 18px;
+ display: flex;
+ align-items: center;
+ margin: 0;
+ padding: 10px 20px 10px 10px;
+ cursor: pointer;
+ transition: all 0.2s;
+ color: #ffffff;
+}
+
+html.dark #swagger-ui section.models h4 svg {
+ transition: all 0.4s;
+ fill: #e2e8f0;
+}
+
+html.dark #swagger-ui section.models h4 span {
+ flex: 1;
+}
+
+html.dark #swagger-ui section.models h4:hover {
+ background: rgba(42, 42, 64, 0.1);
+}
+
+html.dark #swagger-ui section.models h5 {
+ font-size: 16px;
+ margin: 0 0 10px 0;
+ color: #ffffff;
+}
+
+html.dark #swagger-ui section.models .model-jump-to-path {
+ position: relative;
+ top: 5px;
+}
+
+html.dark #swagger-ui section.models .model-jump-to-path .view-line-link {
+ color: #60a5fa;
+}
+
+html.dark #swagger-ui section.models .model-jump-to-path .view-line-link:hover {
+ color: #93c5fd;
+}
+
+html.dark #swagger-ui section.models .model-container {
+ margin: 0 20px 15px;
+ position: relative;
+ transition: all 0.5s;
+ border-radius: 6px;
+ background: rgba(26, 26, 46, 0.4);
+ border: 1px solid rgba(42, 42, 64, 0.3);
+}
+
+html.dark #swagger-ui section.models .model-container:hover {
+ background: rgba(26, 26, 46, 0.6);
+ border-color: rgba(52, 52, 80, 0.5);
+}
+
+html.dark #swagger-ui section.models .model-container:first-of-type {
+ margin: 20px;
+}
+
+html.dark #swagger-ui section.models .model-container:last-of-type {
+ margin: 0 20px;
+}
+
+html.dark #swagger-ui section.models .model-container .models-jump-to-path {
+ position: absolute;
+ top: 8px;
+ right: 5px;
+ opacity: 0.7;
+ color: #94a3b8;
+}
+
+html.dark #swagger-ui section.models .model-container .models-jump-to-path:hover {
+ opacity: 1;
+ color: #60a5fa;
+}
+
+html.dark #swagger-ui section.models .model-box {
+ background: rgba(26, 26, 46, 0.6);
+ border: 1px solid rgba(42, 42, 64, 0.4);
+}
+
+html.dark #swagger-ui .model-box {
+ padding: 12px;
+ display: inline-block;
+ border-radius: 6px;
+ background: rgba(26, 26, 46, 0.8);
+ border: 1px solid rgba(42, 42, 64, 0.5);
+}
+
+html.dark #swagger-ui .model-box .model-jump-to-path {
+ position: relative;
+ top: 4px;
+}
+
+html.dark #swagger-ui .model-box .model-jump-to-path .view-line-link {
+ color: #60a5fa;
+}
+
+html.dark #swagger-ui .model-box .model-jump-to-path .view-line-link:hover {
+ color: #93c5fd;
+}
+
+html.dark #swagger-ui .model-box.deprecated {
+ opacity: 0.4;
+ background: rgba(26, 26, 46, 0.3);
+}
+
+html.dark #swagger-ui .model-deprecated-warning {
+ font-size: 16px;
+ font-weight: 600;
+ margin-right: 1em;
+ color: #fca5a5;
+}
+
+html.dark #swagger-ui span > span.model .brace-close {
+ padding: 0 0 0 10px;
+ color: #e2e8f0;
+}
+
+/* === AUTHORIZATION MODAL === */
+html.dark #swagger-ui .dialog-ux {
+ /* Modal backdrop */
+}
+
+html.dark #swagger-ui .dialog-ux .backdrop-ux {
+ background: rgba(15, 15, 35, 0.85);
+}
+
+html.dark #swagger-ui .dialog-ux .modal-ux {
+ background-color: #1a1a2e;
+ border: 1px solid #2a2a40;
+ box-shadow: 0 10px 30px 0 rgba(0, 0, 0, 0.5);
+}
+
+/* Modal header */
+html.dark #swagger-ui .dialog-ux .modal-ux-header {
+ border-bottom: 1px solid #2a2a40;
+}
+
+html.dark #swagger-ui .dialog-ux .modal-ux-header h3 {
+ color: #ffffff;
+}
+
+html.dark #swagger-ui .dialog-ux .modal-ux-header .close-modal {
+ color: #94a3b8;
+ background: none;
+ border: none;
+ cursor: pointer;
+ font-size: 18px;
+ transition: color 0.2s ease;
+}
+
+html.dark #swagger-ui .dialog-ux .modal-ux-header .close-modal:hover {
+ color: #ffffff;
+}
+
+/* Close button SVG styling */
+html.dark #swagger-ui .dialog-ux .modal-ux-header .close-modal svg {
+ fill: currentColor;
+ width: 16px;
+ height: 16px;
+}
+
+/* Modal content */
+html.dark #swagger-ui .dialog-ux .modal-ux-content {
+ color: #e2e8f0;
+}
+
+html.dark #swagger-ui .dialog-ux .modal-ux-content p {
+ color: #e2e8f0;
+}
+
+html.dark #swagger-ui .dialog-ux .modal-ux-content h4 {
+ color: #ffffff;
+}
+
+/* Auth containers */
+html.dark #swagger-ui .auth-container {
+ border-bottom: 1px solid #2a2a40;
+}
+
+html.dark #swagger-ui .auth-container:last-of-type {
+ border-bottom: none;
+}
+
+html.dark #swagger-ui .auth-container h4 {
+ color: #ffffff;
+}
+
+/* Auth form inputs */
+html.dark #swagger-ui .auth-container input[type="text"],
+html.dark #swagger-ui .auth-container input[type="password"] {
+ background-color: #16213e;
+ color: #e2e8f0;
+ border: 1px solid #2a2a40;
+ border-radius: 4px;
+ padding: 8px 12px;
+}
+
+html.dark #swagger-ui .auth-container input[type="text"]:focus,
+html.dark #swagger-ui .auth-container input[type="password"]:focus {
+ border-color: #60a5fa;
+ box-shadow: 0 0 0 2px rgba(96, 165, 250, 0.2);
+ outline: none;
+}
+
+html.dark #swagger-ui .auth-container input[type="text"]::placeholder,
+html.dark #swagger-ui .auth-container input[type="password"]::placeholder {
+ color: #64748b;
+}
+
+/* Error messages */
+html.dark #swagger-ui .auth-container .errors {
+ background-color: rgba(239, 68, 68, 0.1);
+ color: #fca5a5;
+ border: 1px solid rgba(239, 68, 68, 0.3);
+}
+
+html.dark #swagger-ui .auth-container .errors b {
+ color: #ef4444;
+}
+
+/* Scopes section */
+html.dark #swagger-ui .scopes h2 {
+ color: #ffffff;
+}
+
+html.dark #swagger-ui .scopes h2 a {
+ color: #60a5fa;
+}
+
+html.dark #swagger-ui .scopes h2 a:hover {
+ color: #93c5fd;
+}
+
+/* Scope definitions */
+html.dark #swagger-ui .scope-def {
+ color: #e2e8f0;
+}
+
+/* Checkboxes for scopes */
+html.dark #swagger-ui .auth-container input[type="checkbox"] {
+ appearance: none;
+ width: 16px;
+ height: 16px;
+ border: 2px solid #2a2a40;
+ border-radius: 3px;
+ background-color: #16213e;
+ position: relative;
+ cursor: pointer;
+ margin-right: 8px;
+}
+
+html.dark #swagger-ui .auth-container input[type="checkbox"]:checked {
+ background-color: #60a5fa;
+ border-color: #60a5fa;
+}
+
+html.dark #swagger-ui .auth-container input[type="checkbox"]:checked::after {
+ content: "β";
+ position: absolute;
+ top: -2px;
+ left: 2px;
+ color: #ffffff;
+ font-size: 12px;
+ font-weight: bold;
+}
+
+html.dark #swagger-ui .auth-container input[type="checkbox"]:focus {
+ box-shadow: 0 0 0 2px rgba(96, 165, 250, 0.2);
+ outline: none;
+}
+
+/* Auth button wrapper */
+html.dark #swagger-ui .auth-btn-wrapper {
+ border-top: 1px solid #2a2a40;
+ padding: 15px 20px;
+ background-color: rgba(26, 26, 46, 0.5);
+}
+
+/* Auth buttons */
+html.dark #swagger-ui .auth-btn-wrapper .btn,
+html.dark #swagger-ui .btn.authorize,
+html.dark #swagger-ui .btn[type="submit"] {
+ background-color: #60a5fa !important;
+ color: #ffffff !important;
+ border: none !important;
+ border-radius: 4px;
+ padding: 8px 16px;
+ cursor: pointer;
+ font-weight: 500;
+ transition: background-color 0.2s ease;
+ text-shadow: none !important;
+}
+
+html.dark #swagger-ui .auth-btn-wrapper .btn:hover,
+html.dark #swagger-ui .btn.authorize:hover,
+html.dark #swagger-ui .btn[type="submit"]:hover {
+ background-color: #3b82f6 !important;
+ color: #ffffff !important;
+}
+
+html.dark #swagger-ui .auth-btn-wrapper .btn-done,
+html.dark #swagger-ui .btn-done {
+ background-color: #34d399 !important;
+ color: #ffffff !important;
+}
+
+html.dark #swagger-ui .auth-btn-wrapper .btn-done:hover,
+html.dark #swagger-ui .btn-done:hover {
+ background-color: #10b981 !important;
+ color: #ffffff !important;
+}
+
+/* Cancel/secondary buttons */
+html.dark #swagger-ui .auth-btn-wrapper .btn.cancel {
+ background-color: transparent;
+ color: #94a3b8;
+ border: 1px solid #2a2a40;
+}
+
+html.dark #swagger-ui .auth-btn-wrapper .btn.cancel:hover {
+ background-color: rgba(42, 42, 64, 0.3);
+ color: #ffffff;
+}
+
+/* Labels and form text */
+html.dark #swagger-ui .auth-container label {
+ color: #e2e8f0;
+ font-weight: 500;
+ display: block;
+ margin-bottom: 4px;
+}
+
+/* Auth wrapper (the authorize button in topbar) */
+html.dark #swagger-ui .auth-wrapper .authorize {
+ color: #94a3b8;
+}
+
+html.dark #swagger-ui .auth-wrapper .authorize:hover {
+ color: #60a5fa;
+}
+
+/* Small text and descriptions */
+html.dark #swagger-ui .auth-container small,
+html.dark #swagger-ui .auth-container .description {
+ color: #94a3b8;
+ font-size: 11px;
+}
+
+/* OAuth flow information */
+html.dark #swagger-ui .auth-container .flow {
+ color: #94a3b8;
+ font-style: italic;
+}
+
+/* Token display area */
+html.dark #swagger-ui .auth-container .token {
+ background-color: #16213e;
+ border: 1px solid #2a2a40;
+ border-radius: 4px;
+ padding: 8px;
+ font-family: monospace;
+ font-size: 12px;
+ color: #fbbf24;
+ word-break: break-all;
+}
\ No newline at end of file
diff --git a/docs/images/swagger-login-route.png b/docs/images/swagger-login-route.png
new file mode 100644
index 00000000..cc2258c7
Binary files /dev/null and b/docs/images/swagger-login-route.png differ
diff --git a/docs/images/swagger-user-endpoint.png b/docs/images/swagger-user-endpoint.png
new file mode 100644
index 00000000..799c79cc
Binary files /dev/null and b/docs/images/swagger-user-endpoint.png differ
diff --git a/docs/public/apostrophecms-openapi.yaml b/docs/public/apostrophecms-openapi.yaml
new file mode 100644
index 00000000..ea4c4e68
--- /dev/null
+++ b/docs/public/apostrophecms-openapi.yaml
@@ -0,0 +1,10080 @@
+openapi: 3.1.0
+info:
+ title: ApostropheCMS REST API
+ description: |
+ **π Developer freedom. Editor happiness. It just works.**
+
+ **For production use:** Download this YAML file and update the server URL
+ and cookie names to match your setup.
+
+ The ApostropheCMS REST API allows you to create, read, update, and delete content programmatically.
+ Perfect for building modern websites, mobile apps, and any digital experience that needs flexible content management.
+
+ ## Quick Start Guide
+ 1. **Authentication**: Use the login endpoint to get a bearer token or session cookie
+ 2. **Get Content**: Start with `/@apostrophecms/page` to fetch your page structure
+ 3. **Media Files**: Upload files via `/@apostrophecms/attachment/upload`
+ 4. **Internationalization**: Use `/@apostrophecms/i18n` to localize your content
+
+ ## Content Architecture
+ ApostropheCMS uses a flexible "pieces" system for content types. While the core system provides
+ essential pieces like users and global content, most projects define custom piece types like
+ articles, events, or products using the `@apostrophecms/piece-type` module.
+
+ ## Built-in Piece Types
+ - `@apostrophecms/user` - User accounts and profiles
+ - `@apostrophecms/global` - Site-wide content (customizable with additional fields)
+ - `@apostrophecms/image` - Image file management
+ - `@apostrophecms/file` - General file management (PDFs, documents, etc.)
+
+ ## Built-in Tag Types
+ - `@apostrophecms/image-tag` - Tags for organizing images
+ - `@apostrophecms/file-tag` - Tags for organizing files
+
+ ## Authentication Methods
+ - **Bearer Token**: Recommended for API clients and SPAs
+ - **Session Cookie**: For traditional web applications
+ - **API Key**: For server-to-server communication
+
+ ## Rate Limiting
+ API requests are rate-limited to prevent abuse. See response headers for current limits.
+
+ version: 1.0.0
+ contact:
+ name: ApostropheCMS Support
+ url: https://apostrophecms.com
+ email: support@apostrophecms.com
+ license:
+ name: MIT
+ url: https://github.com/apostrophecms/apostrophe/blob/main/LICENSE.md
+
+externalDocs:
+ description: Full Documentation
+ url: "https://docs.apostrophecms.org"
+
+x-apostrophe:
+ cmsVersion: ">=4.20.0"
+ notes: |
+ Spec versioning follows semver independently of CMS releases.
+ isCore: true
+
+ # Used by the expander to control localization flags & nicer names.
+ pieceTypes:
+ standard:
+ - '@apostrophecms/image'
+ - '@apostrophecms/file'
+ - '@apostrophecms/image-tag'
+ - '@apostrophecms/file-tag'
+ - '@apostrophecms/submitted-draft'
+
+ nonLocalizable:
+ - '@apostrophecms/user'
+ - '@apostrophecms/global'
+
+ marketingTags:
+ '@apostrophecms/image': Media
+ '@apostrophecms/file': Media
+ '@apostrophecms/image-tag': Media
+ '@apostrophecms/file-tag': Media
+ '@apostrophecms/user': Users
+ '@apostrophecms/global': Global Content
+ '@apostrophecms/submitted-draft': Submitted Draft
+
+ # π fallback for any piece not listed above
+ defaultPieceMarketingTag: Custom
+
+ # adds the module name as a second tag
+ includeTechnicalTag: true
+
+security:
+ # adds session authentication as the default
+ - SessionAuth: []
+
+servers:
+ - url: http://localhost:3000/api/v1
+ description: Development server
+ - url: https://your-site.com/api/v1
+ description: Production server (not for online use)
+
+tags:
+ - name: Authentication
+ description: π Login, logout, and session management for API access - start here!
+ - name: Pages
+ description: π Essential for headless sites - page structure, content, and navigation
+ - name: Users
+ description: Built-in user management and authentication
+ - name: Global Content
+ description: Site-wide settings and content that appears across pages
+ - name: Submitted Drafts
+ description: Draft submission workflow and review queue management
+ - name: Media
+ description: File uploads, image management, and media organization
+ - name: Attachments
+ description: File upload utilities and image processing
+ - name: Internationalization
+ description: Multi-language support and locale management
+ - name: Custom
+ description: Project-defined piece types (your own content models)
+
+x-tagGroups:
+ - name: Start Here
+ tags: [Authentication]
+ - name: Content & Media
+ tags: [Pages, Global Content, Submitted Draft, Media, Attachments]
+ - name: People
+ tags: [Users]
+ - name: Internationalization
+ tags: [Internationalization]
+ - name: Custom
+ tags: [Custom]
+
+components:
+ securitySchemes:
+ ApiKeyAuth:
+ type: apiKey
+ in: query
+ name: apikey
+ description: |
+ **Server-to-server authentication** - API key for server-to-server communication.
+ Use as query parameter: ?apikey=your-api-key-here
+
+ Configure in app.js:
+ ```javascript
+ '@apostrophecms/express': {
+ options: {
+ apiKeys: {
+ 'myapikey1029384756': { role: 'admin' }
+ }
+ }
+ }
+ ```
+
+ BearerAuth:
+ type: http
+ scheme: bearer
+ description: |
+ Bearer token authentication (recommended for API clients).
+
+ **Step 1:** Close this dialog box and generate a bearer token using the `POST /@apostrophecms/login/login` endpoint below with:
+ ```json
+ {
+ "username": "your-username",
+ "password": "your-password"
+ }
+ ```
+
+ **Step 2:** Copy **only the token value** from the response (not the full JSON)
+ Example: if response is `{"token": "abc123"}`, paste only `abc123`
+ The token will be sent as: Authorization: Bearer {your-token}
+
+ **Step 3:** Reopen this dialog and paste the token value into the value field.
+
+ SessionAuth:
+ type: apiKey
+ in: cookie
+ name: project-shortname.sid
+ description: |
+ β οΈ **For testing after download only:** Change "project-shortname" in the `SessionAuth` to your actual ApostropheCMS shortname (e.g., "myapp.sid").
+
+ π‘ This authentication won't work when testing in the online ApostropheCMS sandbox. However, you can use the login route to set a cookie you can examine in your browser DevTools.
+ It will be named `project-shortname.sid`.
+
+ **Step 1:** Close this dialog and use the `POST /@apostrophecms/login/login` endpoint below with:
+ ```json
+ {
+ "username": "your-username",
+ "password": "your-password",
+ "session": true
+ }
+ ```
+
+ **Step 2:** Copy the session cookie value from your browser's dev tools
+ and paste it into the "Value" field.
+
+ parameters:
+ Page:
+ name: page
+ in: query
+ description: Page number for pagination (1-based)
+ required: false
+ schema:
+ type: integer
+ minimum: 1
+ default: 1
+ example: 2
+
+ PerPage:
+ name: perPage
+ in: query
+ description: Number of items per page
+ required: false
+ schema:
+ type: integer
+ minimum: 1
+ maximum: 100
+ default: 10
+ example: 25
+
+ Search:
+ name: search
+ in: query
+ description: Search term for filtering results
+ required: false
+ schema:
+ type: string
+ example: "headless cms"
+
+ Autocomplete:
+ name: autocomplete
+ in: query
+ description: Partial word search for autocomplete functionality
+ required: false
+ schema:
+ type: string
+ example: "apost"
+
+ AposMode:
+ name: aposMode
+ in: query
+ description: Request draft or published version of content
+ required: false
+ schema:
+ type: string
+ enum: [draft, published]
+ default: published
+ example: "published"
+
+ AposLocale:
+ name: aposLocale
+ in: query
+ description: Locale for internationalization (e.g., 'en', 'fr', 'es')
+ required: false
+ schema:
+ type: string
+ example: "fr"
+
+ ToLocale:
+ name: toLocale
+ in: path
+ required: true
+ description: Target locale code (e.g., en:us:published)
+ schema:
+ type: string
+ pattern: '^[a-z]{2}(-[A-Z]{2})?$'
+ example: en
+
+ RenderAreas:
+ name: render-areas
+ in: query
+ description: π‘ Render widget areas as HTML instead of returning raw widget data - useful for hybrid architectures
+ required: false
+ schema:
+ type: boolean
+ default: false
+ example: true
+
+ DocumentId:
+ name: _id
+ in: path
+ required: true
+ description: Computed document ID (can optionally include mode and locale, e.g., id:en:published)
+ schema:
+ type: string
+ pattern: '^\S+$'
+ example: "ckitdo5oq004pu69kr6oxo6fr:en:published"
+
+ AposDocId:
+ name: aposDocId
+ in: path
+ required: true
+ description: ApostropheCMS document identifier
+ schema:
+ type: string
+ pattern: '^[a-zA-Z0-9]+$'
+ example: "ckitdo5oq004pu69kr6oxo6fr"
+
+ ImageDocId:
+ name: imageId
+ in: path
+ required: true
+ description: ApostropheCMS document identifier for an image
+ schema:
+ type: string
+ pattern: '^[a-zA-Z0-9]+$'
+ example: "ck9x8v7w2000001l6h8q9d5f0"
+
+ AllPages:
+ name: all
+ in: query
+ description: Return all pages the requester can see (system/orphan pages included). Use with caution for large sites. Default is 0.
+ schema:
+ type: integer
+ enum: [0,1]
+ default: 0
+ example: 1
+
+ FlatResponse:
+ name: flat
+ in: query
+ description: π‘ Return pages in flat array instead of tree structure - easier for some use cases. Default is 0 (nested).
+ schema:
+ type: integer
+ enum: [0,1]
+ default: 0
+ example: 1
+
+ ChildrenParam:
+ name: children
+ in: query
+ description: Include children array in response (set to 'false' to exclude). Default is true.
+ schema:
+ type: boolean
+ default: true
+ example: false
+
+ schemas:
+ _Overview_Fields:
+ type: object
+ description: |
+ # Field Types (editor-facing)
+
+ - `StringField` β basic text
+ - `IntegerField`, `FloatField` β numbers
+ - `SelectField`, `RadioField`, `CheckboxesField` β choices
+ - `AreaField`, `ArrayField`, `ObjectField`
+ - `AttachmentField`, `RelationshipField`, `RelationshipReverseField`
+
+ π See also: **FieldDefinition** (discriminator: `type`).
+ externalDocs:
+ description: ApostropheCMS Field Guide
+ url: https://docs.apostrophecms.org/reference/field-types/
+ title: _Overview_Fields
+ _Overview_Primitives:
+ type: object
+ description: |
+ # Content Primitives (payload-level)
+
+ These are the βdata atomsβ for requests and responses.
+
+ - `AposString`, `AposSlug`, `AposUrl`, `AposEmail`
+ - `AposDateTime`, `AposDate`, `AposTime`
+ - Arrays: `AposStringArray`, `AposIntegerArray`, etc.
+
+ π Defined under **AposPrimitives**.
+ title: _Overview_Primitives
+ _Overview_Advanced:
+ type: object
+ description: |
+ # Advanced / Internal
+
+ Used by OpenAPI for schema defs:
+ - `UiCondition` (for `if`/`requiredIf`)
+ - `OperatorObject` (query operators)
+ - `AreaOptions`, `ArrayOptions`, and other config helpers
+ title: _Overview_Advanced
+ AreaField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - type: object
+ additionalProperties: false
+ properties:
+ type:
+ type: string
+ enum:
+ - area
+ description: Apostrophe field type id.
+ options:
+ $ref: '#/components/schemas/AreaOptions'
+ if:
+ $ref: '#/components/schemas/UiCondition'
+ requiredIf:
+ $ref: '#/components/schemas/UiCondition'
+ required:
+ - type
+ - label
+ - options
+ examples:
+ - type: area
+ label: Main content
+ options:
+ max: 3
+ expanded: true
+ widgets:
+ '@apostrophecms/image': {}
+ '@apostrophecms/rich-text':
+ toolbar:
+ - bold
+ - italic
+ '@apostrophecms/video': {}
+ '@apostrophecms/html': {}
+ groups:
+ basics:
+ label: Basic Content
+ columns: 3
+ widgets:
+ '@apostrophecms/rich-text':
+ toolbar:
+ - bold
+ '@apostrophecms/image': {}
+ embeds:
+ label: Embeds
+ columns: 2
+ widgets:
+ '@apostrophecms/video': {}
+ '@apostrophecms/html': {}
+ title: AreaField
+ AreaOptions:
+ type: object
+ additionalProperties: false
+ properties:
+ widgets:
+ description: |
+ Allowed widget types for this area. Keys are widget module names (e.g., "@apostrophecms/rich-text"). Values are per-widget options that apply *only* in this area.
+ type: object
+ additionalProperties:
+ type: object
+ groups:
+ description: |
+ Organize widgets into groups for the expanded preview menu.
+ Each group has a label, optional columns (1β4, default 3), and its own widgets map (same shape as `widgets`).
+ type: object
+ additionalProperties:
+ $ref: '#/components/schemas/AreaWidgetGroup'
+ max:
+ type: integer
+ description: Maximum number of widgets allowed in this area.
+ expanded:
+ type: boolean
+ description: Use the expanded preview menu UX.
+ required:
+ - widgets
+ title: AreaOptions
+ AreaWidgetGroup:
+ type: object
+ additionalProperties: false
+ properties:
+ label:
+ type: string
+ columns:
+ type: integer
+ minimum: 1
+ maximum: 4
+ description: Number of widget previews per row (default 3).
+ widgets:
+ type: object
+ additionalProperties:
+ type: object
+ required:
+ - label
+ - widgets
+ title: AreaWidgetGroup
+ ArrayField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - type: object
+ additionalProperties: false
+ description: A repeatable list of objects, each with its own field schema.
+ properties:
+ type:
+ type: string
+ enum:
+ - array
+ description: Apostrophe field type id.
+ fields:
+ $ref: '#/components/schemas/Fieldset'
+ min:
+ type: integer
+ description: Minimum number of items (inclusive).
+ max:
+ type: integer
+ description: Maximum number of items (inclusive).
+ titleField:
+ type: string
+ description: Field name in each item used as the item label in the UI.
+ if:
+ $ref: '#/components/schemas/UiCondition'
+ requiredIf:
+ $ref: '#/components/schemas/UiCondition'
+ required:
+ - type
+ - label
+ - fields
+ examples:
+ - type: array
+ label: Tasks
+ min: 0
+ max: 50
+ titleField: title
+ items:
+ type: object
+ properties:
+ title:
+ type: string
+ priority:
+ type: string
+ fields:
+ add:
+ title:
+ type: string
+ label: Task Title
+ priority:
+ type: select
+ label: Priority
+ choices:
+ - label: Low
+ value: low
+ - label: High
+ value: high
+ title: ArrayField
+ AttachmentField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - type: object
+ additionalProperties: false
+ description: |
+ Lets editors upload a single file (image, PDF, etc.).
+ Use an ArrayField of AttachmentField if you need multiple files.
+ properties:
+ type:
+ type: string
+ enum:
+ - attachment
+ description: Apostrophe field type id.
+ accept:
+ oneOf:
+ - type: string
+ description: HTML "accept" string (e.g., "image/*,.pdf"). Use to limitby MIME type and/or extension.
+ - type: array
+ items:
+ type: string
+ description: List of MIME types and/or extensions (e.g., ["image/*",
+ ".pdf"]).
+ maxSize:
+ type: integer
+ description: Optional max file size in bytes (documentation-only hint).
+ if:
+ $ref: '#/components/schemas/UiCondition'
+ requiredIf:
+ $ref: '#/components/schemas/UiCondition'
+ required:
+ - type
+ - label
+ examples:
+ - type: attachment
+ label: Resume (PDF)
+ accept:
+ - .pdf
+ required: true
+ - type: attachment
+ label: Hero Image
+ accept: image/*
+ title: AttachmentField
+ BooleanField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - type: object
+ additionalProperties: false
+ properties:
+ type:
+ type: string
+ enum:
+ - boolean
+ description: Apostrophe field type id.
+ def:
+ type: boolean
+ description: Default value shown in the editor UI.
+ toggle:
+ oneOf:
+ - type: boolean
+ description: |
+ If true, use the alternate "toggle" UI.
+ Labels default to the field label and standard true/false text.
+ - type: object
+ additionalProperties: false
+ description: Configure custom labels for the toggle UI.
+ properties:
+ 'true':
+ type: string
+ description: Label to display when value is true.
+ 'false':
+ type: string
+ description: Label to display when value is false.
+ required:
+ - type
+ - label
+ examples:
+ - type: boolean
+ label: Is this a special item?
+ def: false
+ - type: boolean
+ label: Show related articles?
+ toggle:
+ 'true': Show related articles
+ 'false': Hide related articles
+ title: BooleanField
+ CheckboxesField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - type: object
+ additionalProperties: false
+ properties:
+ type:
+ type: string
+ enum:
+ - checkboxes
+ description: Apostrophe field type id.
+ def:
+ type: array
+ items:
+ oneOf:
+ - type: string
+ - type: number
+ - type: boolean
+ description: Default selected values.
+ choices:
+ oneOf:
+ - type: array
+ description: Static choices for the checkboxes.
+ items:
+ $ref: '#/components/schemas/SelectChoice'
+ - type: string
+ description: Method name that provides choices dynamically.
+ following:
+ oneOf:
+ - type: string
+ - type: array
+ items:
+ type: string
+ description: Populate dynamically based on other fields (supports `<` parent prefixes).
+ followingIgnore:
+ oneOf:
+ - type: boolean
+ - type: array
+ items:
+ type: string
+ description: Ignore some or all followed fields when generating values.
+ if:
+ $ref: '#/components/schemas/UiCondition'
+ requiredIf:
+ $ref: '#/components/schemas/UiCondition'
+ required:
+ - type
+ - label
+ - choices
+ examples:
+ - type: checkboxes
+ label: Tags
+ choices:
+ - label: News
+ value: news
+ - label: Blog
+ value: blog
+ - label: Events
+ value: events
+ def:
+ - news
+ - events
+ title: CheckboxesField
+ ColorField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - type: object
+ additionalProperties: false
+ properties:
+ type:
+ type: string
+ enum:
+ - color
+ description: Apostrophe field type id.
+ def:
+ type: string
+ pattern: ^#(?:[0-9a-fA-F]{3}){1,2}$
+ description: Default hex color (e.g. "#ff0000").
+ if:
+ $ref: '#/components/schemas/UiCondition'
+ requiredIf:
+ $ref: '#/components/schemas/UiCondition'
+ required:
+ - type
+ - label
+ examples:
+ - type: color
+ label: Theme Color
+ def: '#336699'
+ title: ColorField
+ DateField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - $ref: '#/components/schemas/DateBoundaryOptions'
+ - type: object
+ additionalProperties: false
+ properties:
+ type:
+ type: string
+ enum:
+ - date
+ description: Apostrophe field type id.
+ def:
+ type: string
+ format: date
+ description: Default date shown in the editor UI (YYYY-MM-DD).
+ if:
+ $ref: '#/components/schemas/UiCondition'
+ requiredIf:
+ $ref: '#/components/schemas/UiCondition'
+ required:
+ - type
+ - label
+ examples:
+ - type: date
+ label: Publish Date
+ def: '2025-01-01'
+ min: '2020-01-01'
+ max: '2030-12-31'
+ - type: date
+ label: Event Date
+ if:
+ status:
+ $eq: scheduled
+ title: DateField
+ DateAndTimeField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - $ref: '#/components/schemas/DateTimeBoundaryOptions'
+ - type: object
+ additionalProperties: false
+ properties:
+ type:
+ type: string
+ enum:
+ - dateAndTime
+ description: Apostrophe field type id.
+ def:
+ type: string
+ format: date-time
+ description: Default timestamp in RFC 3339 format (e.g., 2025-08-29T13:00:00Z).
+ if:
+ $ref: '#/components/schemas/UiCondition'
+ requiredIf:
+ $ref: '#/components/schemas/UiCondition'
+ required:
+ - type
+ - label
+ examples:
+ - type: dateAndTime
+ label: Starts At
+ def: '2025-08-29T13:00:00Z'
+ min: '2024-01-01T00:00:00Z'
+ max: '2026-12-31T23:59:59Z'
+ - type: dateAndTime
+ label: Reminder At
+ requiredIf:
+ remindersEnabled: true
+ title: DateAndTimeField
+ EmailField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - type: object
+ additionalProperties: false
+ properties:
+ type:
+ type: string
+ enum:
+ - email
+ description: Apostrophe field type id.
+ def:
+ type: string
+ format: email
+ description: Default email address shown in the editor UI.
+ pattern:
+ type: string
+ description: Optional regex for stricter validation (in addition to HTML5
+ email validation).
+ autocomplete:
+ type: string
+ description: Value for the HTML autocomplete attribute. Common values are
+ "email" or "off".
+ if:
+ $ref: '#/components/schemas/UiCondition'
+ requiredIf:
+ $ref: '#/components/schemas/UiCondition'
+ required:
+ - type
+ - label
+ examples:
+ - type: email
+ label: Contact Email
+ def: info@example.com
+ - type: email
+ label: Support Email
+ autocomplete: email
+ requiredIf:
+ supportEnabled: true
+ title: EmailField
+ FloatField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - $ref: '#/components/schemas/NumericRangeOptions'
+ - type: object
+ additionalProperties: false
+ properties:
+ type:
+ type: string
+ enum:
+ - float
+ format:
+ type: string
+ enum:
+ - float
+ description: OpenAPI hint for tooling; always "float".
+ def:
+ type: number
+ format: float
+ description: Default decimal value.
+ examples:
+ - type: float
+ label: Price (USD)
+ help: Enter a decimal price.
+ def: 0.0
+ min: 0
+ max: 99999.99
+ required: true
+ title: FloatField
+ IntegerField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - $ref: '#/components/schemas/NumericRangeOptions'
+ - type: object
+ additionalProperties: false
+ properties:
+ type:
+ type: string
+ enum:
+ - integer
+ description: Apostrophe field type id.
+ def:
+ type: integer
+ description: Default integer value shown in the editor UI.
+ required:
+ - type
+ - label
+ examples:
+ - type: integer
+ label: Age
+ min: 0
+ max: 120
+ def: 18
+ - type: integer
+ label: Estimated Hours
+ min: 1
+ max: 999
+ title: IntegerField
+ ObjectField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - type: object
+ additionalProperties: false
+ description: A nested object with its own field schema.
+ properties:
+ type:
+ type: string
+ enum:
+ - object
+ fields:
+ $ref: '#/components/schemas/Fieldset'
+ if:
+ $ref: '#/components/schemas/UiCondition'
+ requiredIf:
+ $ref: '#/components/schemas/UiCondition'
+ required:
+ - type
+ - label
+ - fields
+ title: ObjectField
+ OembedField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - type: object
+ additionalProperties: false
+ properties:
+ type:
+ type: string
+ enum:
+ - oembed
+ description: Apostrophe field type id.
+ if:
+ $ref: '#/components/schemas/UiCondition'
+ requiredIf:
+ $ref: '#/components/schemas/UiCondition'
+ required:
+ - type
+ - label
+ description: |
+ Lets editors paste a media URL from an oEmbed-compatible host.
+ The editor shows an immediate preview once a valid URL is entered.
+ Stored value is an object snapshot (url/title/thumbnail).
+ examples:
+ - type: oembed
+ label: Featured video
+ title: OembedField
+ PasswordField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - type: object
+ additionalProperties: false
+ properties:
+ type:
+ type: string
+ enum:
+ - password
+ description: Apostrophe field type id.
+ def:
+ type: string
+ description: Default password value (generally not used).
+ min:
+ type: integer
+ description: Minimum number of characters required.
+ max:
+ type: integer
+ description: Maximum number of characters allowed.
+ pattern:
+ type: string
+ description: Regex to enforce password rules (e.g., at least one number).
+ autocomplete:
+ type: string
+ description: HTML autocomplete attribute, usually "new-password" or "current-password".
+ if:
+ $ref: '#/components/schemas/UiCondition'
+ requiredIf:
+ $ref: '#/components/schemas/UiCondition'
+ required:
+ - type
+ - label
+ examples:
+ - type: password
+ label: Account Password
+ min: 8
+ autocomplete: new-password
+ title: PasswordField
+ RadioField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - type: object
+ additionalProperties: false
+ properties:
+ type:
+ type: string
+ enum:
+ - radio
+ description: Apostrophe field type id.
+ def:
+ oneOf:
+ - type: string
+ - type: number
+ - type: boolean
+ description: Default selected value.
+ choices:
+ oneOf:
+ - type: array
+ description: Static choices to render as radio buttons.
+ items:
+ $ref: '#/components/schemas/SelectChoice'
+ - type: string
+ description: Method name that provides choices (e.g. "statusChoices").
+ following:
+ oneOf:
+ - type: string
+ - type: array
+ items:
+ type: string
+ description: Populate dynamically based on other fields (supports `<` parent prefixes).
+ followingIgnore:
+ oneOf:
+ - type: boolean
+ - type: array
+ items:
+ type: string
+ description: Ignore some or all followed fields when generating values.
+ if:
+ $ref: '#/components/schemas/UiCondition'
+ requiredIf:
+ $ref: '#/components/schemas/UiCondition'
+ required:
+ - type
+ - label
+ - choices
+ examples:
+ - type: radio
+ label: Priority
+ choices:
+ - label: Low
+ value: low
+ - label: High
+ value: high
+ def: low
+ - type: radio
+ label: Status
+ choices: statusChoices
+ title: RadioField
+ RangeField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - $ref: '#/components/schemas/NumericRangeOptions'
+ - type: object
+ additionalProperties: false
+ properties:
+ type:
+ type: string
+ enum:
+ - range
+ description: Apostrophe field type id.
+ def:
+ type: number
+ description: Default slider value in the editor UI.
+ step:
+ type: number
+ description: Increment step for the slider. If omitted, defaults to 1.
+ min:
+ type: number
+ description: Minimum value for the slider.
+ max:
+ type: number
+ description: Maximum value for the slider.
+ if:
+ $ref: '#/components/schemas/UiCondition'
+ requiredIf:
+ $ref: '#/components/schemas/UiCondition'
+ required:
+ - type
+ - label
+ examples:
+ - type: range
+ label: Satisfaction
+ min: 1
+ max: 10
+ step: 1
+ def: 5
+ - type: range
+ label: Volume
+ min: 0
+ max: 100
+ step: 5
+ def: 50
+ title: RangeField
+ RelationshipField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - type: object
+ additionalProperties: false
+ description: |
+ Relate this document to one or more docs of another type (pieces/pages).
+ Use `max: 1` for a single-select join; omit `max` (or set >1) for multi-select.
+ properties:
+ type:
+ type: string
+ enum:
+ - relationship
+ description: Apostrophe field type id.
+ withType:
+ type: string
+ description: Module name of the related doc type (e.g., "article", "@apostrophecms/image").
+ min:
+ type: integer
+ description: Minimum number of related docs required (inclusive).
+ max:
+ type: integer
+ description: Maximum number of related docs allowed (inclusive).
+ fields:
+ $ref: '#/components/schemas/Fieldset'
+ builders:
+ type: object
+ additionalProperties: true
+ description: |
+ Apostrophe cursor builders for the related query (e.g., {project: { title: 1 }, sort: { title: 1 } }).
+ if:
+ $ref: '#/components/schemas/UiCondition'
+ requiredIf:
+ $ref: '#/components/schemas/UiCondition'
+ required:
+ - type
+ - label
+ - withType
+ examples:
+ - type: relationship
+ label: Author
+ withType: person
+ max: 1
+ builders:
+ project:
+ title: 1
+ _url: 1
+ - type: relationship
+ label: Related Articles
+ withType: article
+ min: 0
+ max: 5
+ fields:
+ add:
+ relationshipRole:
+ type: select
+ label: Role
+ choices:
+ - label: Primary
+ value: primary
+ - label: Secondary
+ value: secondary
+ builders:
+ project:
+ title: 1
+ _url: 1
+ sort:
+ title: 1
+ title: RelationshipField
+ RelationshipReverseField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - type: object
+ additionalProperties: false
+ description: |
+ Read-only reverse side of a forward `relationship` field defined on another type.
+ Use this to show βreferenced byβ links without storing ids here.
+ properties:
+ type:
+ type: string
+ enum:
+ - relationshipReverse
+ description: Apostrophe field type id.
+ withType:
+ type: string
+ description: Module name that holds the forward relationship.
+ reverseOf:
+ type: string
+ description: |
+ Name of the forward relationship field on `withType` (e.g.,"_authors" on "article").
+ builders:
+ type: object
+ additionalProperties: true
+ description: Cursor builders applied when populating the reverse join.
+ if:
+ $ref: '#/components/schemas/UiCondition'
+ requiredIf:
+ $ref: '#/components/schemas/UiCondition'
+ required:
+ - type
+ - label
+ - withType
+ - reverseOf
+ examples:
+ - type: relationshipReverse
+ label: Articles referencing this person
+ withType: article
+ reverseOf: _authors
+ builders:
+ project:
+ title: 1
+ _url: 1
+ title: RelationshipReverseField
+ SelectField:
+ allOf:
+ - $ref: '#/components/schemas/BaseField'
+ - type: object
+ additionalProperties: false
+ properties:
+ type:
+ type: string
+ enum:
+ - select
+ description: Apostrophe field type id.
+ def:
+ oneOf:
+ - type: string
+ - type: number
+ - type: boolean
+ - type: array
+ items:
+ oneOf:
+ - type: string
+ - type: number
+ - type: boolean
+ description: |
+ Default value. If `multiple: true`, this should be an array.
+ multiple:
+ type: boolean
+ description: Allow selecting multiple values (stores an array).
+ choices:
+ oneOf:
+ - type: array
+ description: Static choices for the select dropdown.
+ items:
+ $ref: '#/components/schemas/SelectChoice'
+ - type: string
+ description: |
+ Name of a method that returns choices (e.g. "sponsorNames").
+ May be "module:method" to reference another module.
+ following:
+ oneOf:
+ - type: string
+ - type: array
+ items:
+ type: string
+ description: Populate dynamically based on other fieldsβ values (supports `<` parent prefixes).
+ followingIgnore:
+ oneOf:
+ - type: boolean
+ - type: array
+ items:
+ type: string
+ description: Ignore some or all followed fields when generating values.
+ required:
+ - type
+ - label
+ examples:
+ - type: select
+ label: Task Priority
+ choices:
+ - label: Low
+ value: low
+ - label: Medium
+ value: medium
+ - label: High
+ value: high
+ - label: Critical
+ value: critical
+ def: medium
+ - type: select
+ label: Tags
+ multiple: true
+ choices:
+ - label: News
+ value: news
+ - label: Blog
+ value: blog
+ - label: Events
+ value: events
+ def:
+ - news
+ - events
+ - type: select
+ label: Sponsor
+ choices: sponsorNames
+ following:
+ -
Welcome to our company! We've been serving customers since 2020.
+ _id: widget-123 + seoFields: + metaDescription: Learn about our company, mission, and values + ogTitle: About Our Company + ogDescription: Discover our story and what drives us forward + _ancestors: + - root-page-id + _children: [] + _url: https://example.com/about-us + _edit: true + _publish: true + title: Page + User: + type: object + description: | + Built-in user piece type for account management. + + **Base Properties**: Inherited from @apostrophecms/piece-type + **User-Specific Properties**: title, username, email, role, disabled + + π‘ Developers can add custom fields to the user piece type in their project configuration. + properties: + _id: + type: string + description: Unique identifier + example: clx1234567890abcdef + title: + type: string + description: User's display name + example: John Developer + username: + type: string + description: Login username (must be unique) + example: johndeveloper + email: + type: string + format: email + description: User's email address + example: john@example.com + role: + type: string + description: User role - determines permissions + enum: + - guest + - contributor + - editor + - admin + example: editor + disabled: + type: boolean + description: Whether the user account is disabled + default: false + archived: + type: boolean + description: Whether the user is archived + default: false + visibility: + type: string + description: Visibility setting + enum: + - public + - loginRequired + default: loginRequired + type: + type: string + example: '@apostrophecms/user' + slug: + type: string + example: user-johndeveloper + createdAt: + type: string + format: date-time + description: Account creation date + updatedAt: + type: string + format: date-time + description: Last update date + title: User + Global: + type: object + description: | + 'Built-in global content piece type for site-wide settings. + + π‘ Developers can add custom fields to the global piece type in their project + configuration. + properties: + _id: + type: string + description: Unique identifier + example: global + title: + type: string + description: Default title field + readOnly: true + example: global + slug: + type: string + description: Default slug field + readOnly: true + example: global + type: + type: string + example: '@apostrophecms/global' + readOnly: true + additionalProperties: true + title: Global + GlobalPatch: + type: object + description: | + Allows for patching of costom user added fields. + It blocks the modification of the title, slu, and type fields. + properties: + title: + type: string + description: Default title field + readOnly: true + example: global + slug: + type: string + description: Default slug field + readOnly: true + example: global + type: + type: string + example: '@apostrophecms/global' + readOnly: true + additionalProperties: true + Attachment: + type: object + description: File attachment information from upload endpoint + properties: + _id: + type: string + description: Unique attachment identifier + example: ckj0akbxa003vp39kfbxgb8zg + _url: + type: string + description: URL to the original file + example: https://example.net/uploads/attachments/ckj0akbxa003vp39kfbxgb8zg-blue-box.png + _urls: + type: object + description: URLs for different image sizes (images only) + additionalProperties: + type: string + name: + type: string + description: Slugified filename + example: blue-box + title: + type: string + description: Sortified filename + example: blue box + extension: + type: string + description: File extension + example: png + type: + type: string + example: attachment + group: + type: string + description: File group type + example: images + length: + type: integer + description: File size in bytes + example: 10497 + md5: + type: string + description: MD5 checksum + example: 630eeaaecd0bdc07c4a82eeca4c07588 + width: + type: integer + description: Image width in pixels (images only) + example: 600 + height: + type: integer + description: Image height in pixels (images only) + example: 106 + landscape: + type: boolean + description: Whether image is landscape orientation (images only) + portrait: + type: boolean + description: Whether image is portrait orientation (images only) + docIds: + type: array + items: + type: string + description: IDs of documents using this attachment + archivedDocIds: + type: array + items: + type: string + description: IDs of archived documents using this attachment + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: Attachment + Image: + type: object + description: Built-in image/media piece type for managing photos and graphics + properties: + _id: + type: string + description: Unique identifier + example: clx1234567890abcdef + title: + type: string + description: Image title/alt text + example: Hero banner image + slug: + type: string + example: hero-banner-image + type: + type: string + example: '@apostrophecms/image' + archived: + type: boolean + default: false + visibility: + type: string + enum: + - public + - loginRequired + default: public + attachment: + type: object + description: File attachment information + properties: + _id: + type: string + name: + type: string + example: hero-banner + extension: + type: string + example: jpg + length: + type: integer + description: File size in bytes + url: + type: string + description: Public URL to access the image + example: /uploads/attachments/clx123/hero-banner.jpg + credit: + type: string + description: Image credit or attribution + tags: + type: array + items: + type: string + description: Image tags for organization + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: Image + FileObject: + type: object + description: Built-in file piece type for general file uploads (PDFs, documents, + etc.) + properties: + _id: + type: string + description: Unique identifier + example: clx1234567890abcdef + title: + type: string + description: File title/description + example: Company Brochure + slug: + type: string + example: company-brochure + type: + type: string + example: '@apostrophecms/file' + archived: + type: boolean + default: false + visibility: + type: string + enum: + - public + - loginRequired + default: public + attachment: + type: object + description: File attachment information + properties: + _id: + type: string + name: + type: string + example: company-brochure + extension: + type: string + example: pdf + length: + type: integer + description: File size in bytes + url: + type: string + description: Public URL to access the file + example: /uploads/attachments/clx123/company-brochure.pdf + description: + type: string + description: File description + tags: + type: array + items: + type: string + description: File tags for organization + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: File + ImageTag: + type: object + description: Built-in image tag piece type for organizing images + properties: + _id: + type: string + example: clx1234567890abcdef + title: + type: string + description: Tag name + example: Hero Images + slug: + type: string + description: URL-friendly tag name + example: hero-images + type: + type: string + example: '@apostrophecms/image-tag' + archived: + type: boolean + default: false + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: ImageTag + FileTag: + type: object + description: Built-in file tag piece type for organizing files + properties: + _id: + type: string + example: clx1234567890abcdef + title: + type: string + description: Tag name + example: Marketing Materials + slug: + type: string + description: URL-friendly tag name + example: marketing-materials + type: + type: string + example: '@apostrophecms/file-tag' + archived: + type: boolean + default: false + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + title: FileTag + SubmittedDraft: + type: object + properties: + _id: + type: string + description: Unique identifier for the submitted draft + example: clh123abc456def789 + type: + type: string + description: Document type identifier + example: '@apostrophecms/submitted-draft' + title: + type: string + description: Title of the submitted draft + example: New Article Draft + slug: + type: string + description: URL-friendly version of the title + example: new-article-draft + content: + type: string + description: Content of the submitted draft + example: This is the draft content awaiting review. + author: + type: string + description: Author of the submitted draft + example: John Doe + authorId: + type: string + description: ID of the user who created the draft + example: clh456def789abc123 + submissionNotes: + type: string + description: Notes from the submitter about the draft + example: Please review for accuracy and tone. + priority: + type: string + enum: + - low + - normal + - high + - urgent + description: Priority level for review + example: normal + category: + type: string + description: Category or type of content being submitted + example: blog-post + status: + type: string + enum: + - draft + - submitted + - under-review + - approved + - rejected + - published + description: Current status of the submitted draft + example: submitted + submittedAt: + type: string + format: date-time + description: When the draft was submitted for review + example: '2024-03-15T10:30:00Z' + reviewedAt: + type: string + format: date-time + description: When the draft was last reviewed + example: '2024-03-16T14:20:00Z' + reviewedBy: + type: string + description: ID of the user who reviewed the draft + example: clh789ghi012jkl345 + reviewNotes: + type: string + description: Notes from the reviewer + example: Approved with minor suggestions for improvement. + publishedAt: + type: string + format: date-time + description: When the draft was published (if applicable) + example: '2024-03-17T09:00:00Z' + archived: + type: boolean + description: Whether the submitted draft is archived + default: false + createdAt: + type: string + format: date-time + description: When the submitted draft was created + example: '2024-03-15T09:15:00Z' + updatedAt: + type: string + format: date-time + description: When the submitted draft was last updated + example: '2024-03-15T10:30:00Z' + aposLocale: + type: string + description: Locale for this version of the content + example: en + aposMode: + type: string + enum: + - draft + - published + description: Content mode (draft or published) + example: draft + required: + - _id + - type + - title + - content + - author + - status + - createdAt + - updatedAt + title: SubmittedDraft + PieceResponse: + type: object + properties: + success: + type: boolean + description: Whether the request was successful + data: + type: object + description: The piece data + error: + type: string + description: Error message if success is false + title: PieceResponse + PaginatedResponse: + type: object + description: Standard response format for list endpoints + properties: + success: + type: boolean + data: + type: object + properties: + results: + type: array + items: + type: object + description: Array of pieces (type depends on endpoint) + pages: + type: integer + description: Total number of pages + currentPage: + type: integer + description: Current page number (1-based) + total: + type: integer + description: Total number of items across all pages + title: PaginatedResponse + CreatePieceRequest: + type: object + description: Generic structure for creating any piece type + required: + - title + properties: + title: + type: string + description: Piece title (required for all piece types) + slug: + type: string + description: URL slug (auto-generated from title if not provided) + visibility: + type: string + enum: + - public + - loginRequired + description: Visibility setting + default: public + archived: + type: boolean + description: Whether the piece is archived + default: false + title: CreatePieceRequest + ApiError: + type: object + properties: + status: + type: integer + description: HTTP status code, e.g., 401 + code: + type: string + description: Application error code (optional) + message: + type: string + description: Human-readable error message + details: + type: object + additionalProperties: true + description: Extra context about the error + required: + - message + title: Error + LocalesResponse: + type: object + description: Object containing all configured locales + additionalProperties: + type: object + properties: + label: + type: string + description: Human-readable locale name + example: English + _edit: + type: boolean + description: Whether current user can edit content in this locale + example: true + example: + en: + label: English + _edit: true + fr: + label: French + _edit: false + title: LocalesResponse + LocaleRequest: + type: object + required: + - locale + properties: + locale: + type: string + description: Target locale code + example: fr + contextDocId: + type: string + description: Optional document ID for the path + example: cloydg3ka0005qcls5vmg8sb9 + clipboard: + type: string + description: Optional clipboard content for cross-domain situations + example: exampleClipboardContent + title: LocaleRequest + PageLocaleResult: + type: object + properties: + _id: + type: string + description: | + Document ID with locale and mode (format: docId:locale:mode) + example: "s9gjqtw1ok7wxvewdu78xnes:en:published" + aposLocale: + type: string + description: | + Locale identifier with mode (format: locale:mode) + example: "en:published" + required: + - _id + - aposLocale + PageLocalesResponse: + type: object + properties: + results: + type: array + items: + $ref: '#/components/schemas/PageLocaleResult' + required: + - results + SameHostnameResponse: + type: object + additionalProperties: false + required: + - redirectTo + properties: + redirectTo: + type: string + description: Path to redirect to within same hostname + pattern: ^/(?!/).* + example: /fr/page-slug + title: SameHostnameResponse + DifferentHostnameResponse: + type: object + additionalProperties: false + required: + - redirectTo + properties: + redirectTo: + type: string + format: uri + description: Full URL to redirect to with cross-domain session token + pattern: ^[A-Za-z][A-Za-z0-9+.-]*:// + example: https://fr.example.com/french-example-page?aposCrossDomainSessionToken=generated_token + title: DifferentHostnameResponse + ExistInLocaleRequest: + type: object + required: + - ids + - locale + - mode + properties: + ids: + type: array + items: + type: string + description: Array of document IDs to check + example: + - cloydg3ka0005qcls5vmg8sb9 + - cloydg3ka0005qcls5vmg8sb8 + locale: + type: string + description: Locale to check documents in + example: fr + mode: + type: string + enum: + - draft + - published + description: Mode to check documents in + example: published + title: ExistInLocaleRequest + ExistInLocaleResponse: + type: object + properties: + originalLocaleIds: + type: array + items: + type: string + description: Array of document IDs in the original locale and mode + example: + - cloydg3ka0005qcls5vmg8sb9:en:published + - cloydg3ka0005qcls5vmg8sb8:en:published + newLocaleIds: + type: array + items: + type: string + description: Array of document IDs in the new locale + example: + - cloydg3ka0005qcls5vmg8sb9:fr:published + - cloydg3ka0005qcls5vmg8sb8:fr:published + aposDocIds: + type: array + items: + type: string + description: Array of aposDocId values for the documents + example: + - cloydg3ka0005qcls5vmg8sb9 + - cloydg3ka0005qcls5vmg8sb8 + title: ExistInLocaleResponse + PageTreeResponse: + type: object + description: Complete page data with nested children structure - perfect for building + navigation + properties: + _id: + type: string + description: Unique document identifier + example: ckhdscx5900054z9k88uqs16w + orphan: + type: boolean + description: Whether page is excluded from navigation menus + example: false + visibility: + type: string + enum: + - public + - loginRequired + - private + description: Page visibility setting - controls who can view this page + example: public + type: + type: string + description: Page type identifier (configured in your project) + example: '@apostrophecms/home-page' + title: + type: string + description: Page title - used for navigation and SEO + example: Home Page + slug: + type: string + description: URL slug for the page + example: / + rank: + type: integer + description: Order among sibling pages (for navigation sorting) + example: 0 + level: + type: integer + description: Page tree depth level (0 = home page) + example: 0 + path: + type: string + description: Ancestor path of page IDs + example: ckhdscx5900054z9k88uqs16w + _url: + type: string + format: uri + description: Complete page URL - use this for links + example: http://localhost:3000/ + _ancestors: + type: array + items: + $ref: '#/components/schemas/PageSummary' + description: Array of ancestor pages (for breadcrumbs) + _children: + type: array + items: + $ref: '#/components/schemas/PageTreeResponse' + description: Array of child pages (nested structure) + createdAt: + type: string + format: date-time + description: ISO date of creation + updatedAt: + type: string + format: date-time + description: ISO date of last update + archived: + type: boolean + description: Whether page is archived (hidden from normal views) + example: false + historicUrls: + type: array + items: + type: string + description: Previous URLs that redirect to this page (SEO preservation) + metaType: + type: string + example: doc + titleSortified: + type: string + description: Sortable version of title + updatedBy: + $ref: '#/components/schemas/User' + _edit: + type: boolean + description: Whether current user can edit this page + title: PageTreeResponse + FlatPageResponse: + type: object + description: Pages returned as flat array instead of tree structure + properties: + results: + type: array + items: + allOf: + - $ref: '#/components/schemas/PageTreeResponse' + - type: object + properties: + _children: + type: array + items: + type: string + description: Array of child page IDs (in flat response) + _ancestors: + type: array + items: + type: string + description: Array of ancestor page IDs (in flat response) + title: FlatPageResponse + PageSummary: + type: object + description: Abbreviated page information for ancestors/references + properties: + _id: + type: string + title: + type: string + slug: + type: string + type: + type: string + _url: + type: string + format: uri + level: + type: integer + rank: + type: integer + title: PageSummary + PageCreateRequest: + type: object + required: + - _targetId + - _position + - title + properties: + _targetId: + type: string + description: ID of target page for positioning (_home and _archive are convenience + values) + example: ckhdscx5900054z9k88uqs16w + _position: + oneOf: + - type: string + enum: + - before + - after + - firstChild + - lastChild + - type: integer + minimum: 0 + description: Position relative to target (string values) or child index (number) + example: firstChild + _copyingId: + type: string + description: Optional ID of existing page to copy properties from + title: + type: string + description: Page title + example: My New Page + slug: + type: string + description: URL slug (auto-generated if not provided) + example: /my-new-page + type: + type: string + description: Page type (must be configured in your project) + example: default-page + visibility: + type: string + enum: + - public + - loginRequired + - private + default: public + description: Who can view this page + title: PageCreateRequest + PageUpdateRequest: + type: object + properties: + _targetId: + type: string + description: ID of target page for repositioning (required if moving page) + _position: + oneOf: + - type: string + enum: + - before + - after + - firstChild + - lastChild + - type: integer + minimum: 0 + description: New position (required if moving page) + title: + type: string + description: Updated page title + slug: + type: string + description: Updated URL slug + visibility: + type: string + enum: + - public + - loginRequired + - private + description: Updated visibility setting + updatedBy: + $ref: '#/components/schemas/User' + title: PageUpdateRequest + Widget: + type: object + description: Content widget within an area - represents a piece of structured + content + properties: + _id: + type: string + metaType: + type: string + enum: + - widget + type: + type: string + description: Widget type (e.g., rich-text, image, custom widgets) + example: '@apostrophecms/rich-text' + _edit: + type: boolean + _docId: + type: string + content: + type: string + description: HTML content for rich text widgets (filtered based on widget + configuration) + example:Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum + nibh, ut fermentum massa justo sit amet risus.
+ import: + type: object + description: Import configuration for external content (used during creation/update) + properties: + baseUrl: + type: string + format: uri + description: Base URL for resolving relative image URLs + example: https://myoldsite.com + html: + type: string + description: HTML content to import (images will be automatically imported) + example: 'Here is some text.
+ +
'
+ imageTags:
+ type: array
+ items:
+ type: string
+ description: Array of existing @apostrophecms/image-tag piece _ids to
+ apply to imported images
+ example:
+ - tag-piece-id-1
+ - tag-piece-id-2
+ title: Widget
+ PageDotNotationUpdate:
+ type: object
+ description: Keys may use Apostrophe dot notation to target nested content.
+ propertyNames:
+ pattern: ^[a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+|\.\d+)+$
+ additionalProperties:
+ oneOf:
+ - type: string
+ - type: number
+ - type: boolean
+ - type: object
+ - type: array
+ items: {}
+ - type: 'null'
+ title: PageDotNotationUpdate
+ BaseField:
+ type: object
+ additionalProperties: false
+ properties:
+ type:
+ type: string
+ description: Apostrophe field type id (e.g., "float", "string", "boolean").
+ label:
+ type: string
+ description: Human-readable label for editors.
+ help:
+ type: string
+ description: Short helper text shown in the UI.
+ htmlHelp:
+ type: string
+ description: Rich helper text (HTML allowed by Apostrophe).
+ def:
+ description: Default value for this field (type varies by field).
+ required:
+ type: boolean
+ description: If true, value must be provided.
+ readOnly:
+ type: boolean
+ description: If true, UI should render as read-only (Apostrophe option).
+ hidden:
+ type: boolean
+ description: If true, hide in editor UI.
+ if:
+ $ref: '#/components/schemas/UiCondition'
+ requiredIf:
+ $ref: '#/components/schemas/UiCondition'
+ required:
+ - type
+ - label
+ title: BaseField
+ UiCondition:
+ type: object
+ additionalProperties: false
+ description: |
+ 'Apostrophe conditional used by `if` and `requiredIf`.
+ Keys are field paths (including `<` parent access and dot notation) or method calls with `()`.
+ Values are either simple equality (primitive) or an operator object. Supports `$or` / `$and` groups. See OperatorObject.
+ properties:
+ $or:
+ type: array
+ description: Any condition group may pass. :contentReference[oaicite:1]{index=1}
+ items:
+ $ref: '#/components/schemas/UiCondition'
+ $and:
+ type: array
+ description: All condition groups must pass. (Redundant at the same level,
+ but useful when nested with `$or`.) :contentReference[oaicite:2]{index=2}
+ items:
+ $ref: '#/components/schemas/UiCondition'
+ patternProperties:
+ ^[A-Za-z_][\\w-]*(?:\\.(?:length|\\d+|[A-Za-z_][\\w-]*))*$:
+ $ref: '#/components/schemas/FieldPredicate'
+ ^<+[A-Za-z_][\\w-]*(?:\\.(?:length|\\d+|[A-Za-z_][\\w-]*))*$:
+ $ref: '#/components/schemas/FieldPredicate'
+ ^(?:[A-Za-z0-9_-]+:)?[A-Za-z0-9_-]+\\(\\)$:
+ $ref: '#/components/schemas/FieldPredicate'
+ examples:
+ - priority:
+ $in:
+ - high
+ - critical
+ estimatedHours:
+ $gte: 20
+ assignee.length:
+ $gt: 0
+ - $or:
+ - seenMovie: true
+ - featuredMovie(): true
+ title: UiCondition
+ FieldPredicate:
+ description: A simple equality (primitive) or an OperatorObject. :contentReference[oaicite:5]{index=5}
+ oneOf:
+ - type: string
+ - type: number
+ - type: boolean
+ - type: 'null'
+ - $ref: '#/components/schemas/OperatorObject'
+ title: FieldPredicate
+ OperatorObject:
+ type: object
+ additionalProperties: false
+ description: |
+ MongoDB-style operators supported by Apostrophe conditions.
+ Note:
+ `$eq` has special handling with arrays (see docs).
+ `$exists: true` means not null/undefined; empty string is truthy so use `$ne: ''''` or check `.length`.
+ properties:
+ $eq: {}
+ $ne: {}
+ $gt:
+ type: number
+ $gte:
+ type: number
+ $lt:
+ type: number
+ $lte:
+ type: number
+ $in:
+ type: array
+ items: {}
+ $nin:
+ type: array
+ items: {}
+ $exists:
+ type: boolean
+ example:
+ $in:
+ - high
+ - critical
+ title: OperatorObject
+ NumericRangeOptions:
+ type: object
+ additionalProperties: false
+ properties:
+ min:
+ type: number
+ description: Minimum allowed value (inclusive).
+ max:
+ type: number
+ description: Maximum allowed value (inclusive)
+ title: NumericRangeOptions
+ DateBoundaryOptions:
+ type: object
+ additionalProperties: false
+ properties:
+ min:
+ type: string
+ format: date
+ description: Minimum allowed date (inclusive), ISO-8601 (YYYY-MM-DD).
+ max:
+ type: string
+ format: date
+ description: Maximum allowed date (inclusive), ISO-8601 (YYYY-MM-DD).
+ title: DateBoundaryOptions
+ DateTimeBoundaryOptions:
+ type: object
+ additionalProperties: false
+ properties:
+ min:
+ type: string
+ format: date-time
+ description: Minimum allowed timestamp (inclusive), RFC 3339.
+ max:
+ type: string
+ format: date-time
+ description: Maximum allowed timestamp (inclusive), RFC 3339.
+ title: DateTimeBoundaryOptions
+ RelationshipEntry:
+ type: object
+ description: |
+ One relationship entry. Always includes the related document `_id`.
+ If you declared per-relationship `fields`, those values are stored alongside `_id` here.
+ properties:
+ _id:
+ type: string
+ description: Id of the related document.
+ required:
+ - _id
+ additionalProperties: true
+ title: RelationshipEntry
+ BulkOperationRequest:
+ type: object
+ properties:
+ _ids:
+ type: array
+ items:
+ type: string
+ description: Array of document IDs to operate on
+ example: ["doc1:en:draft", "doc2:en:published"]
+ required:
+ - _ids
+ BulkOperationResponse:
+ type: object
+ properties:
+ success:
+ type: boolean
+ modified:
+ type: integer
+ description: Number of documents affected
+ errors:
+ type: array
+ items:
+ type: string
+ Fieldset:
+ type: object
+ additionalProperties: false
+ properties:
+ add:
+ type: object
+ additionalProperties:
+ $ref: '#/components/schemas/FieldDefinition'
+ required:
+ - add
+ title: Fieldset
+ FieldDefinition:
+ oneOf:
+ - $ref: '#/components/schemas/BooleanField'
+ - $ref: '#/components/schemas/StringField'
+ - $ref: '#/components/schemas/IntegerField'
+ - $ref: '#/components/schemas/FloatField'
+ - $ref: '#/components/schemas/SelectField'
+ - $ref: '#/components/schemas/RadioField'
+ - $ref: '#/components/schemas/CheckboxesField'
+ - $ref: '#/components/schemas/PasswordField'
+ - $ref: '#/components/schemas/ColorField'
+ - $ref: '#/components/schemas/DateField'
+ - $ref: '#/components/schemas/DateAndTimeField'
+ - $ref: '#/components/schemas/TimeField'
+ - $ref: '#/components/schemas/EmailField'
+ - $ref: '#/components/schemas/UrlField'
+ - $ref: '#/components/schemas/SlugField'
+ - $ref: '#/components/schemas/OembedField'
+ - $ref: '#/components/schemas/RangeField'
+ - $ref: '#/components/schemas/ObjectField'
+ - $ref: '#/components/schemas/ArrayField'
+ - $ref: '#/components/schemas/AreaField'
+ - $ref: '#/components/schemas/AttachmentField'
+ - $ref: '#/components/schemas/RelationshipField'
+ - $ref: '#/components/schemas/RelationshipReverseField'
+ discriminator:
+ propertyName: type
+ mapping:
+ boolean: '#/components/schemas/BooleanField'
+ string: '#/components/schemas/StringField'
+ integer: '#/components/schemas/IntegerField'
+ float: '#/components/schemas/FloatField'
+ select: '#/components/schemas/SelectField'
+ radio: '#/components/schemas/RadioField'
+ checkboxes: '#/components/schemas/CheckboxesField'
+ password: '#/components/schemas/PasswordField'
+ color: '#/components/schemas/ColorField'
+ date: '#/components/schemas/DateField'
+ dateAndTime: '#/components/schemas/DateAndTimeField'
+ time: '#/components/schemas/TimeField'
+ email: '#/components/schemas/EmailField'
+ url: '#/components/schemas/UrlField'
+ slug: '#/components/schemas/SlugField'
+ oembed: '#/components/schemas/OembedField'
+ range: '#/components/schemas/RangeField'
+ object: '#/components/schemas/ObjectField'
+ array: '#/components/schemas/ArrayField'
+ area: '#/components/schemas/AreaField'
+ attachment: '#/components/schemas/AttachmentField'
+ relationship: '#/components/schemas/RelationshipField'
+ relationshipReverse: '#/components/schemas/RelationshipReverseField'
+ title: FieldDefinition
+ AposPrimitives:
+ $id: https://example.com/apostrophe/primitives
+ $schema: https://json-schema.org/draft/2020-12/schema
+ description: |
+ Reusable primitive data shapes for ApostropheCMS document payloads.
+ Use these in content models; keep field-definition objects separate.
+ $defs:
+ AposString:
+ type: string
+ AposStringArray:
+ type: array
+ items:
+ $ref: '#/components/schemas/AposPrimitives/$defs/AposString'
+ AposSlug:
+ type: string
+ pattern: ^[a-z0-9][a-z0-9-]*$
+ description: Slug string stored in the document, usually lowercase and URL-safe (e.g. "my-article", "blog/my-custom-page").
+ AposEmail:
+ type: string
+ format: email
+ description: A valid email address per RFC 5322, as stored in documents and returned via the API.
+ AposURI:
+ type: string
+ format: uri
+ description: |
+ A valid absolute URL (RFC 3986).
+ Usually stored with protocol, e.g., "https://example.com".
+ AposPassword:
+ type: string
+ description: Password string as entered. Apostrophe typically hashes thisbefore storage; API usage depends on context.
+ AposDateTime:
+ type: string
+ format: date-time
+ description: ISO-8601 calendar date (YYYY-MM-DD).
+ AposDate:
+ type: string
+ format: date
+ description: RFC 3339 timestamp (e.g., 2025-08-29T13:00:00Z).
+ AposTime:
+ type: string
+ pattern: ^(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d$
+ description: Time string stored in documents, always in HH:MM:SS (24-hour).
+ AposInteger:
+ type: integer
+ AposIntegerArray:
+ type: array
+ items:
+ $ref: '#/components/schemas/AposPrimitives/$defs/AposInteger'
+ AposFloat:
+ type: number
+ AposFloatArray:
+ type: array
+ items:
+ $ref: '#/components/schemas/AposPrimitives/$defs/AposFloat'
+ AposRange:
+ type: number
+ description: Stored numeric value selected via the slider (integer or float, depending on configuration).
+ AposBoolean:
+ type: boolean
+ AposBooleanArray:
+ type: array
+ items:
+ $ref: '#/components/schemas/AposPrimitives/$defs/AposBoolean'
+ AposRadio:
+ oneOf:
+ - type: string
+ - type: number
+ - type: boolean
+ description: The stored value for a radio field (one of the choice values).
+ AposCheckboxes:
+ type: array
+ items:
+ oneOf:
+ - type: string
+ - type: number
+ - type: boolean
+ description: The stored values for a checkboxes field. Each item is one of the configured choice values.
+ AposOembed:
+ type: object
+ additionalProperties: false
+ properties:
+ url:
+ type: string
+ format: uri
+ description: Original media URL saved by the editor.
+ title:
+ type: string
+ description: Title snapshot from the oEmbed response at save time.
+ thumbnail:
+ type: string
+ format: uri
+ description: Thumbnail URL snapshot from the oEmbed response at save time.
+ required:
+ - url
+ description: |
+ Data stored on the document: a snapshot of the oEmbed resource.
+ Fetch full embed HTML at runtime via GET `/api/v1/@apostrophecms/oembed/query?url=Updated content
" + responses: + '200': + description: Page updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Page' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + put: + tags: + - Pages + summary: Replace page + description: | + Completely replace a page document. + + **Use cases:** + - Complete page updates + - Moving pages in the tree structure + - Replacing page content entirely + + Requires `_targetId` and `_position` for page tree positioning. + operationId: PagePutById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + - $ref: '#/components/parameters/RenderAreas' + requestBody: + required: true + content: + application/json: + schema: + allOf: + - $ref: '#/components/schemas/PageCreateRequest' + - type: object + required: + - _targetId + - _position + responses: + '200': + description: Page replaced successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Page' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/page/{_id}/dismiss-submission: + post: + tags: + - Pages + summary: Dismiss page submission + description: Dismiss a pending submission for the specified page, removing it from the review queue + operationId: PageDismissSubmissionById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Page submission dismissed successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Page' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/page/{_id}/locale/{toLocale}: + get: + tags: + - Pages + summary: Get page in specific locale + description: Retrieve the specified page in a specific locale + operationId: PageGetLocaleById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/ToLocale' + responses: + '200': + description: Page locale retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Page' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/page/{_id}/locales: + get: + tags: + - Pages + summary: Get page locales + description: Retrieve all available locales for the specified page + operationId: PageGetLocalesById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Page locales retrieved successfully + content: + application/json: + schema: + type: object + properties: + results: + type: array + items: + type: object + properties: + _id: + type: string + description: Document ID with locale and mode + example: "s9gjqtw1ok7wxvewdu78xnes:en:published" + aposLocale: + type: string + description: Locale identifier with mode + example: "en:published" + required: + - _id + - aposLocale + required: + - results + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/page/{_id}/localize: + post: + tags: + - Pages + summary: Localize page + description: Create a localized version of the specified page for a specific language/region + operationId: PageLocalizeById + parameters: + - $ref: '#/components/parameters/DocumentId' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + toLocale: + type: string + description: Target locale for localization + example: "es" + responses: + '200': + description: Page localized successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Page' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/page/{_id}/publish: + post: + tags: + - Pages + summary: Publish page + description: | + **Advanced Feature**: Publish a draft page to make it live. + + Moves a page from draft mode to published mode, making it visible + to public users. Essential for content workflows where editors + create drafts before publishing. + + **Use cases:** + - Content approval workflows + - Scheduled publishing systems + - Editorial review processes + + The `_id` can be from either the draft or published version, + or you can use the `aposDocId` to reference the document. + operationId: PagePublishById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposLocale' + responses: + '200': + description: Page published successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Page' + examples: + published_page: + summary: Successfully published page + value: + _id: "ckhdscx5900054z9k88uqs16w:en:published" + title: "My Published Page" + slug: "/my-published-page" + type: "default-page" + _url: "https://example.com/my-published-page" + updatedAt: "2024-12-18T10:30:00.000Z" + '400': + description: Bad request - cannot publish (e.g., validation errors) + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + examples: + validation_error: + summary: Page validation failed + value: + error: "Validation failed" + message: "Page title is required before publishing" + '401': + $ref: '#/components/responses/Unauthorized' + '403': + description: Forbidden - insufficient permissions to publish pages + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '404': + description: Page not found or no draft version exists + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + examples: + no_draft: + summary: No draft version to publish + value: + error: "Not Found" + message: "No draft version of this page exists" + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/page/{_id}/revert-draft-to-published: + post: + tags: + - Pages + summary: Revert draft to published + description: Revert the draft version of the specified page back to its published state + operationId: PageRevertDraftToPublishedById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Page draft reverted to published successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Page' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/page/{_id}/revert-published-to-previous: + post: + tags: + - Pages + summary: Revert published to previous + description: Revert the published version of the specified page to its previous published state + operationId: PageRevertPublishedToPreviousById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Page published version reverted to previous successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Page' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/page/{_id}/share: + post: + tags: + - Pages + summary: Share page + description: Generate a sharing link or configure sharing permissions for the specified page + operationId: PageShareById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Page shared successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Page' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/page/{_id}/submit: + post: + tags: + - Pages + summary: Submit page + description: Submit the specified page for review and approval workflow + operationId: PageSubmitById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Page submitted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Page' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/page/{_id}/unpublish: + post: + tags: + - Pages + summary: Unpublish page + description: Unpublish the specified page, removing it from public visibility while preserving the content + operationId: PageUnpublishById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + responses: + '200': + description: Page unpublished successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Page' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + # Built-in piece types + # User + /@apostrophecms/user: + get: + tags: + - Users + summary: List users + description: Retrieve a list of users with optional filtering, sorting, and pagination + operationId: UserList + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + results: + type: array + items: + $ref: '#/components/schemas/User' + pages: + type: integer + description: Total number of pages + currentPage: + type: integer + description: Current page number + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + post: + tags: + - Users + summary: Create user + description: Create a new user account with the specified properties + operationId: UserCreate + parameters: + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - title + - username + - email + properties: + title: + type: string + description: Display name for the user + example: "John Doe" + username: + type: string + description: Unique username for login + example: "johndoe" + email: + type: string + format: email + description: User's email address + example: "john.doe@example.com" + password: + type: string + format: password + description: User's password + example: "securePassword123" + firstName: + type: string + description: User's first name + example: "John" + lastName: + type: string + description: User's last name + example: "Doe" + role: + type: string + description: User's role/permission level + example: "editor" + disabled: + type: boolean + description: Whether the user account is disabled + default: false + responses: + '200': + description: User created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '409': + description: Conflict - username or email already exists + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/user/archive: + post: + tags: + - Users + summary: Archive users + description: Archive multiple users, making them inactive while preserving their data + operationId: UserArchive + responses: + '200': + description: Archive job started successfully + content: + application/json: + schema: + type: object + properties: + jobId: + type: string + description: ID of the background job processing the archive operation + example: "b4kef9mgstbi5trzsw5dyfqm" + required: + - jobId + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/user/localize: + post: + tags: + - Users + summary: Localize users + description: Create or update localized versions of users for different languages/regions + operationId: UserLocalize + responses: + '200': + description: Users localized successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/user/publish: + post: + tags: + - Users + summary: Publish users + description: Publish multiple users, making them live and visible + operationId: UserPublish + responses: + '200': + description: Users published successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/user/restore: + post: + tags: + - Users + summary: Restore users + description: Restore previously archived users, making them active again + operationId: UserRestore + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkOperationRequest' + responses: + '200': + description: Users restored successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/user/{_id}: + delete: + tags: + - Users + summary: Delete user + description: Permanently delete a specific user by ID (requires appropriate permissions) + operationId: UserDeleteById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: User deleted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + get: + tags: + - Users + summary: Get user + description: Retrieve a specific user by ID + operationId: UserGetById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + - $ref: '#/components/parameters/RenderAreas' + responses: + '200': + description: User retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + patch: + tags: + - Users + summary: Update user + description: Partially update a specific user by ID using PATCH semantics + operationId: UserPatchById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + title: + type: string + description: Display name for the user + example: "John Doe" + email: + type: string + format: email + description: User's email address + example: "john.doe@example.com" + firstName: + type: string + description: User's first name + example: "John" + lastName: + type: string + description: User's last name + example: "Doe" + role: + type: string + description: User's role/permission level + example: "editor" + disabled: + type: boolean + description: Whether the user account is disabled + responses: + '200': + description: User updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + put: + tags: + - Users + summary: Replace user + description: Completely replace a specific user by ID using PUT semantics + operationId: UserPutById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - title + - username + - email + properties: + title: + type: string + description: Display name for the user + example: "John Doe" + username: + type: string + description: Unique username for login + example: "johndoe" + email: + type: string + format: email + description: User's email address + example: "john.doe@example.com" + firstName: + type: string + description: User's first name + example: "John" + lastName: + type: string + description: User's last name + example: "Doe" + role: + type: string + description: User's role/permission level + example: "editor" + disabled: + type: boolean + description: Whether the user account is disabled + default: false + responses: + '200': + description: User replaced successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/user/{_id}/dismiss-submission: + post: + tags: + - Users + summary: Dismiss user submission + description: Dismiss a pending submission for the specified user, removing it from the review queue + operationId: UserDismissSubmissionById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: User submission dismissed successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/user/{_id}/locale/{toLocale}: + get: + tags: + - Users + summary: Get user locale + description: Retrieve the specified user in a specific locale + operationId: UserGetLocaleById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/ToLocale' + responses: + '200': + description: User locale retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/user/{_id}/locales: + get: + tags: + - Users + summary: Get user locales + description: Retrieve all available locales for the specified user + operationId: UserGetLocalesById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: User locales retrieved successfully + content: + application/json: + schema: + type: array + items: + type: string + example: ["en", "es", "fr", "de"] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/user/{_id}/localize: + post: + tags: + - Users + summary: Localize user + description: Create a localized version of the specified user for a specific language/region + operationId: UserLocalizeById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: User localized successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/user/{_id}/publish: + post: + tags: + - Users + summary: Publish user + description: Publish the specified user, making them live and visible + operationId: UserPublishById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: User published successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/user/{_id}/revert-draft-to-published: + post: + tags: + - Users + summary: Revert draft to published + description: Revert the draft version of the specified user back to its published state + operationId: UserRevertDraftToPublishedById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: User draft reverted to published successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/user/{_id}/revert-published-to-previous: + post: + tags: + - Users + summary: Revert published to previous + description: Revert the published version of the specified user to its previous published state + operationId: UserRevertPublishedToPreviousById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: User published version reverted to previous successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/user/{_id}/share: + post: + tags: + - Users + summary: Share user + description: Generate a sharing link or configure sharing permissions for the specified user + operationId: UserShareById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: User shared successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/user/{_id}/submit: + post: + tags: + - Users + summary: Submit user + description: Submit the specified user for review and approval workflow + operationId: UserSubmitById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: User submitted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/user/{_id}/unpublish: + post: + tags: + - Users + summary: Unpublish user + description: Unpublish the specified user, removing them from public visibility while preserving the content + operationId: UserUnpublishById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: User unpublished successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + # Global + /@apostrophecms/global: + get: + tags: + - Global Content + summary: Get global content + description: Retrieve global site configuration and content that appears across all pages + operationId: GlobalGet + parameters: + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + responses: + '200': + description: Successful response + content: + application/json: + schema: + allOf: + - $ref: '#/components/schemas/PaginatedResponse' + - type: object + properties: + results: + type: array + items: + $ref: '#/components/schemas/Global' + + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + post: + tags: + - Global Content + summary: Update global content + description: Update global site configuration and content (requires editor permissions or higher) + operationId: GlobalPost + parameters: + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + title: + type: string + description: Global content title + example: "Site Global Settings" + footerContent: + type: string + description: Footer content that appears on all pages + example: "Β© 2024 My Website. All rights reserved." + contactInfo: + type: object + description: Site-wide contact information + properties: + email: + type: string + format: email + example: "contact@example.com" + phone: + type: string + example: "+1 (555) 123-4567" + address: + type: string + example: "123 Main St, City, State 12345" + socialMedia: + type: object + description: Social media links + properties: + facebook: + type: string + format: uri + example: "https://facebook.com/mysite" + twitter: + type: string + format: uri + example: "https://twitter.com/mysite" + linkedin: + type: string + format: uri + example: "https://linkedin.com/company/mysite" + siteSettings: + type: object + description: Global site configuration + properties: + siteName: + type: string + example: "My Website" + tagline: + type: string + example: "Welcome to our amazing site" + maintenanceMode: + type: boolean + default: false + responses: + '200': + description: Global content updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Global' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/global/archive: + post: + tags: + - Global Content + summary: Archive global document + description: Archive the global document, making it inactive while preserving its data + operationId: GlobalArchive + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkOperationRequest' + responses: + '200': + description: Archive job started successfully + content: + application/json: + schema: + type: object + properties: + jobId: + type: string + description: ID of the background job processing the archive operation + example: "b4kef9mgstbi5trzsw5dyfqm" + required: + - jobId + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/global/localize: + post: + tags: + - Global Content + summary: Localize global document + description: Create or update localized versions of the global document for different languages/regions + operationId: GlobalLocalize + responses: + '200': + description: Global localized successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Global' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/global/publish: + post: + tags: + - Global Content + summary: Publish global document + description: Publish the global document, making it live and visible to end users + operationId: GlobalPublish + responses: + '200': + description: Global published successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Global' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/global/restore: + post: + tags: + - Global Content + summary: Restore global document + description: Restore a previously archived global document, making it active again + operationId: GlobalRestore + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkOperationRequest' + responses: + '200': + description: Global restored successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Global' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/global/{_id}: + delete: + tags: + - Global Content + summary: Delete global document + description: Permanently delete a specific global document by ID (requires appropriate permissions) + operationId: GlobalDeleteById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Global deleted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Global' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + get: + tags: + - Global Content + summary: Get global document + description: Retrieve a specific global document by ID (requires appropriate permissions) + operationId: GlobalGetById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Global retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Global' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + patch: + tags: + - Global Content + summary: Update global document + description: | + Partially update a specific global document by ID using PATCH semantics. + Writes must target the draft mode. + operationId: GlobalPatchById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/GlobalPatch' + responses: + '200': + description: Global updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Global' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + put: + tags: + - Global Content + summary: Replace global document + description: Completely replace a specific global document by ID using PUT semantics + operationId: GlobalPutById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Global replaced successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Global' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/global/{_id}/dismiss-submission: + post: + tags: + - Global Content + summary: Dismiss global submission + description: Dismiss a pending submission for the specified global document, removing it from the review queue + operationId: GlobalDismissSubmissionById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Global submission dismissed successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Global' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/global/{_id}/locale/{toLocale}: + get: + tags: + - Global Content + summary: Get global document locale + description: Retrieve the specified global document in a specific locale + operationId: GlobalGetLocaleById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/ToLocale' + responses: + '200': + description: Global locale retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Global' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/global/{_id}/locales: + get: + tags: + - Global Content + summary: Get global document locales + description: Retrieve all available locales for the specified global document + operationId: GlobalGetLocalesById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Global locales retrieved successfully + content: + application/json: + schema: + type: array + items: + type: string + example: ["en", "es", "fr", "de"] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/global/{_id}/localize: + post: + tags: + - Global Content + summary: Localize global document + description: Create a localized version of the specified global document for a specific language/region + operationId: GlobalLocalizeById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Global localized successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Global' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/global/{_id}/publish: + post: + tags: + - Global Content + summary: Publish global document + description: Publish the specified global document, making it live and visible to end users + operationId: GlobalPublishById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Global published successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Global' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/global/{_id}/revert-draft-to-published: + post: + tags: + - Global Content + summary: Revert draft to published + description: Revert the draft version of the specified global document back to its published state + operationId: GlobalRevertDraftToPublishedById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Global draft reverted to published successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Global' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/global/{_id}/revert-published-to-previous: + post: + tags: + - Global Content + summary: Revert published to previous + description: Revert the published version of the specified global document to its previous published state + operationId: GlobalRevertPublishedToPreviousById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Global published version reverted to previous successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Global' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/global/{_id}/share: + post: + tags: + - Global Content + summary: Share global document + description: Generate a sharing link or configure sharing permissions for the specified global document + operationId: GlobalShareById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Global shared successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Global' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/global/{_id}/submit: + post: + tags: + - Global Content + summary: Submit global document + description: Submit the specified global document for review and approval workflow + operationId: GlobalSubmitById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Global submitted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Global' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/global/{_id}/unpublish: + post: + tags: + - Global Content + summary: Unpublish global document + description: Unpublish the specified global document, removing it from public visibility while preserving the content + operationId: GlobalUnpublishById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Global unpublished successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Global' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + # Image + /@apostrophecms/image: + get: + tags: + - Media + summary: Get images + description: | + Retrieve images from the media library. + Authentication is required for all requests other than GET requests + for images with defined publicApiProjection. + operationId: ImageGet + parameters: + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/PerPage' + - $ref: '#/components/parameters/Search' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + - $ref: '#/components/parameters/RenderAreas' + responses: + '200': + description: Images retrieved successfully + content: + application/json: + schema: + allOf: + - $ref: '#/components/schemas/PaginatedResponse' + - type: object + properties: + results: + type: array + items: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + - {} # Allows unauthenticated access if publicApiProjection is defined + + post: + tags: + - Media + summary: Create image + description: Create a new image document (requires prior attachment upload) + operationId: ImagePost + parameters: + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - title + - attachment + properties: + title: + type: string + example: "Beautiful Landscape" + attachment: + $ref: '#/components/schemas/Attachment' + description: Attachment object from upload endpoint + alt: + type: string + description: Alt text for accessibility + example: "A beautiful mountain landscape at sunset" + credit: + type: string + description: Photo credit + example: "Photo by John Doe" + responses: + '200': + description: Image created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image/archive: + post: + tags: + - Media + summary: Archive images + description: Archive multiple images, making them inactive while preserving their data + operationId: ImageArchive + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkOperationRequest' + responses: + '200': + description: Archive job started successfully + content: + application/json: + schema: + type: object + properties: + jobId: + type: string + description: ID of the background job processing the archive operation + example: "b4kef9mgstbi5trzsw5dyfqm" + required: + - jobId + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image/autocrop: + post: + tags: + - Media + summary: Auto-crop images + description: Automatically crop uploaded images using intelligent cropping algorithms + operationId: ImageAutocrop + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + _ids: + type: array + items: + type: string + description: Array of image IDs to auto-crop + cropRatio: + type: string + description: Desired aspect ratio for cropping + example: "16:9" + responses: + '200': + description: Images auto-cropped successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image/localize: + post: + tags: + - Media + summary: Localize images + description: Create or update localized versions of images for different languages/regions + operationId: ImageLocalize + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + _ids: + type: array + items: + type: string + description: Array of image IDs to localize + toLocale: + type: string + description: Target locale for localization + example: "es" + responses: + '200': + description: Images localized successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image/publish: + post: + tags: + - Media + summary: Publish images + description: Bulk publish multiple images, making them live and visible to end users + operationId: ImagePublish + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + _ids: + type: array + items: + type: string + description: Array of image IDs to publish + responses: + '200': + description: Images published successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image/restore: + post: + tags: + - Media + summary: Restore images + description: Restore previously archived images, making them active again + operationId: ImageRestore + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkOperationRequest' + responses: + '200': + description: Images restored successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image/tag: + post: + tags: + - Media + summary: Tag images + description: Add tags to multiple images for better organization and searchability + operationId: ImageTag + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + _ids: + type: array + items: + type: string + description: Array of image IDs to tag + tags: + type: array + items: + type: string + description: Array of tags to add to the images + example: ["landscape", "nature", "sunset"] + responses: + '200': + description: Images tagged successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image/{_id}: + get: + tags: + - Media + summary: Get image document + description: | + Retrieve a specific image by ID from the media library. + Authentication is required for all requests other than GET requests + for images with defined publicApiProjection. + operationId: ImageGetById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + - $ref: '#/components/parameters/RenderAreas' + responses: + '200': + description: Image retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + - {} # Allows unauthenticated access if publicApiProjection is defined + + put: + tags: + - Media + summary: Replace image document + description: Completely replace an image document by ID using PUT semantics + operationId: ImagePutById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - title + - attachment + properties: + title: + type: string + example: "Beautiful Landscape" + attachment: + $ref: '#/components/schemas/Attachment' + description: Attachment object from upload endpoint + alt: + type: string + description: Alt text for accessibility + example: "A beautiful mountain landscape at sunset" + credit: + type: string + description: Photo credit + example: "Photo by John Doe" + responses: + '200': + description: Image replaced successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + patch: + tags: + - Media + summary: Update image document + description: Partially update a specific image document by ID using PATCH semantics + operationId: ImagePatchById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + title: + type: string + example: "Beautiful Landscape" + alt: + type: string + description: Alt text for accessibility + example: "A beautiful mountain landscape at sunset" + credit: + type: string + description: Photo credit + example: "Photo by John Doe" + description: Only include fields to update + responses: + '200': + description: Image updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + delete: + tags: + - Media + summary: Delete image document + description: Permanently delete a specific image document by ID (requires appropriate permissions) + operationId: ImageDeleteById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image deleted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image/{_id}/dismiss-submission: + post: + tags: + - Media + summary: Dismiss image submission + description: Dismiss a pending submission for the specified image document, removing it from the review queue + operationId: ImageDismissSubmissionById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image submission dismissed successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image/{_id}/locale/{toLocale}: + get: + tags: + - Media + summary: Get image document locale + description: Retrieve the specified image document in a specific locale + operationId: ImageGetLocaleById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/ToLocale' + responses: + '200': + description: Image locale retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image/{_id}/locales: + get: + tags: + - Media + summary: Get image document locales + description: Retrieve all available locales for the specified image document + operationId: ImageGetLocalesById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image locales retrieved successfully + content: + application/json: + schema: + type: array + items: + type: string + example: ["en", "es", "fr", "de"] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image/{_id}/localize: + post: + tags: + - Media + summary: Localize image document + description: Create a localized version of the specified image document for a specific language/region + operationId: ImageLocalizeById + parameters: + - $ref: '#/components/parameters/DocumentId' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + toLocale: + type: string + description: Target locale for localization + example: "es" + responses: + '200': + description: Image localized successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image/{_id}/publish: + post: + tags: + - Media + summary: Publish image document + description: Publish the specified image document, making it live and visible to end users + operationId: ImagePublishById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image published successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image/{_id}/revert-draft-to-published: + post: + tags: + - Media + summary: Revert image draft to published + description: Revert the draft version of the specified image document back to its published state + operationId: ImageRevertDraftToPublishedById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image draft reverted to published successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image/{_id}/revert-published-to-previous: + post: + tags: + - Media + summary: Revert image published to previous + description: Revert the published version of the specified image document to its previous published state + operationId: ImageRevertPublishedToPreviousById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image published version reverted to previous successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image/{_id}/share: + post: + tags: + - Media + summary: Share image document + description: Generate a sharing link or configure sharing permissions for the specified image document + operationId: ImageShareById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image shared successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image/{imageId}/src: + get: + tags: + - Media + summary: Get image source URL + description: Retrieve the source URL for a specific image, with optional size and format parameters + operationId: ImageGetSrcById + parameters: + - $ref: '#/components/parameters/ImageDocId' + - name: size + in: query + description: Image size variant + schema: + type: string + enum: [thumbnail, small, medium, large, original] + default: original + - name: format + in: query + description: Image format + schema: + type: string + enum: [jpg, jpeg, png, webp, avif] + - name: quality + in: query + description: Image quality (1-100) + schema: + type: integer + minimum: 1 + maximum: 100 + default: 80 + responses: + '200': + description: Image source URL retrieved successfully + content: + application/json: + schema: + type: object + properties: + url: + type: string + format: uri + description: Direct URL to the image file + example: "https://example.com/uploads/images/landscape-large.jpg" + width: + type: integer + description: Image width in pixels + example: 1920 + height: + type: integer + description: Image height in pixels + example: 1080 + format: + type: string + description: Image format + example: "jpg" + size: + type: integer + description: File size in bytes + example: 245760 + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + - {} # Allows unauthenticated access for public images + + /@apostrophecms/image/{_id}/submit: + post: + tags: + - Media + summary: Submit image document + description: Submit the specified image document for review and approval workflow + operationId: ImageSubmitById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image submitted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image/{_id}/unpublish: + post: + tags: + - Media + summary: Unpublish image document + description: Unpublish the specified image document, removing it from public visibility while preserving the content + operationId: ImageUnpublishById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image unpublished successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Image' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + # Files + /@apostrophecms/file: + get: + tags: + - Media + summary: List files + description: Retrieve a paginated list of files from the media library + operationId: FileGet + parameters: + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/PerPage' + - $ref: '#/components/parameters/Search' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + - $ref: '#/components/parameters/RenderAreas' + responses: + '200': + description: Files retrieved successfully + content: + application/json: + schema: + allOf: + - $ref: '#/components/schemas/PaginatedResponse' + - type: object + properties: + results: + type: array + items: + $ref: '#/components/schemas/FileObject' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + - {} # Allows unauthenticated access if publicApiProjection is defined + + post: + tags: + - Media + summary: Create file + description: Create a new file document (requires prior attachment upload) + operationId: FilePost + parameters: + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - title + - attachment + properties: + title: + type: string + example: "Important Document" + attachment: + $ref: '#/components/schemas/Attachment' + description: Attachment object from upload endpoint + description: + type: string + description: File description + example: "Quarterly report PDF" + responses: + '200': + description: File created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileObject' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file/archive: + post: + tags: + - Media + summary: Archive files + description: Archive multiple files, making them inactive while preserving their data + operationId: FileArchive + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkOperationRequest' + responses: + '200': + description: Archive job started successfully + content: + application/json: + schema: + type: object + properties: + jobId: + type: string + description: ID of the background job processing the archive operation + example: "b4kef9mgstbi5trzsw5dyfqm" + required: + - jobId + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file/localize: + post: + tags: + - Media + summary: Localize files + description: Create or update localized versions of files for different languages/regions + operationId: FileLocalize + responses: + '200': + description: Files localized successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/FileObject' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file/publish: + post: + tags: + - Media + summary: Publish files + description: Bulk publish multiple files, making them live and visible to end users + operationId: FilePublish + responses: + '200': + description: Files published successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/FileObject' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file/restore: + post: + tags: + - Media + summary: Restore files + description: Restore previously archived files, making them active again + operationId: FileRestore + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkOperationRequest' + responses: + '200': + description: Files restored successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/FileObject' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file/{_id}: + delete: + tags: + - Media + summary: Delete file + description: Permanently delete a specific file by ID (requires appropriate permissions) + operationId: FileDeleteById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + responses: + '200': + description: File deleted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileObject' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + get: + tags: + - Media + summary: Get file by ID + description: Retrieve a specific file by ID from the media library + operationId: FileGetById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + - $ref: '#/components/parameters/RenderAreas' + responses: + '200': + description: File retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileObject' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + - {} # Allows unauthenticated access if publicApiProjection is defined + + patch: + tags: + - Media + summary: Update file + description: Partially update a specific file by ID using PATCH semantics + operationId: FilePatchById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + title: + type: string + description: File title + example: "Important Document" + description: + type: string + description: File description + example: "Quarterly report PDF" + description: Only include fields to update + responses: + '200': + description: File updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileObject' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + put: + tags: + - Media + summary: Replace file + description: Completely replace a specific file by ID using PUT semantics + operationId: FilePutById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - title + - attachment + properties: + title: + type: string + example: "Important Document" + attachment: + $ref: '#/components/schemas/Attachment' + description: Attachment object from upload endpoint + description: + type: string + description: File description + example: "Quarterly report PDF" + responses: + '200': + description: File replaced successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileObject' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file/{_id}/dismiss-submission: + post: + tags: + - Media + summary: Dismiss file submission + description: Dismiss a pending submission for the specified file, removing it from the review queue + operationId: FileDismissSubmissionById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: File submission dismissed successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileObject' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file/{_id}/locale/{toLocale}: + get: + tags: + - Media + summary: Get file locale + description: Retrieve the specified file in a specific locale + operationId: FileGetLocaleById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/ToLocale' + responses: + '200': + description: File locale retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileObject' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file/{_id}/locales: + get: + tags: + - Media + summary: Get file locales + description: Retrieve all available locales for the specified file + operationId: FileGetLocalesById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: File locales retrieved successfully + content: + application/json: + schema: + type: array + items: + type: string + example: ["en", "es", "fr", "de"] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file/{_id}/localize: + post: + tags: + - Media + summary: Localize file + description: Create a localized version of the specified file for a specific language/region + operationId: FileLocalizeById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: File localized successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileObject' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file/{_id}/publish: + post: + tags: + - Media + summary: Publish file + description: Publish the specified file, making it live and visible to end users + operationId: FilePublishById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: File published successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileObject' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file/{_id}/revert-draft-to-published: + post: + tags: + - Media + summary: Revert file draft to published + description: Revert the draft version of the specified file back to its published state + operationId: FileRevertDraftToPublishedById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: File draft reverted to published successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileObject' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file/{_id}/revert-published-to-previous: + post: + tags: + - Media + summary: Revert file published to previous + description: Revert the published version of the specified file to its previous published state + operationId: FileRevertPublishedToPreviousById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: File published version reverted to previous successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileObject' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file/{_id}/share: + post: + tags: + - Media + summary: Share file + description: Generate a sharing link or configure sharing permissions for the specified file + operationId: FileShareById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: File shared successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileObject' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file/{_id}/submit: + post: + tags: + - Media + summary: Submit file + description: Submit the specified file for review and approval workflow + operationId: FileSubmitById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: File submitted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileObject' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file/{_id}/unpublish: + post: + tags: + - Media + summary: Unpublish file + description: Unpublish the specified file, removing it from public visibility while preserving the content + operationId: FileUnpublishById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: File unpublished successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileObject' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + # Image-tags + /@apostrophecms/image-tag: + get: + tags: + - Media + summary: Get image tags + description: Retrieve image tags for organizing images + operationId: ImageTagGet + parameters: + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/PerPage' + - $ref: '#/components/parameters/Search' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + - $ref: '#/components/parameters/RenderAreas' + responses: + '200': + description: Successful response + content: + application/json: + schema: + allOf: + - $ref: '#/components/schemas/PaginatedResponse' + - type: object + properties: + results: + type: array + items: + $ref: '#/components/schemas/ImageTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + - {} # Allows unauthenticated access if publicApiProjection is defined + + post: + tags: + - Media + summary: Create image tag + description: Create a new image tag for organizing images + operationId: ImageTagPost + parameters: + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - title + properties: + title: + type: string + example: "Hero Images" + description: Tag name + slug: + type: string + example: "hero-images" + description: URL-friendly identifier (auto-generated if not provided) + responses: + '200': + description: Image tag created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ImageTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image-tag/archive: + post: + tags: + - Media + summary: Archive image tags + description: Archive multiple image tags, making them inactive while preserving their data + operationId: ImageTagArchive + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkOperationRequest' + responses: + '200': + description: Archive job started successfully + content: + application/json: + schema: + type: object + properties: + jobId: + type: string + description: ID of the background job processing the archive operation + example: "b4kef9mgstbi5trzsw5dyfqm" + required: + - jobId + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image-tag/localize: + post: + tags: + - Media + summary: Localize image tags + description: Create or update localized versions of image tags for different languages/regions + operationId: ImageTagLocalize + responses: + '200': + description: Image tags localized successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ImageTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image-tag/publish: + post: + tags: + - Media + summary: Publish image tags + description: Publish multiple image tags, making them live and visible to end users + operationId: ImageTagPublish + responses: + '200': + description: Image tags published successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ImageTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image-tag/restore: + post: + tags: + - Media + summary: Restore image tags + description: Restore previously archived image tags, making them active again + operationId: ImageTagRestore + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkOperationRequest' + responses: + '200': + description: Image tags restored successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ImageTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image-tag/{_id}: + delete: + tags: + - Media + summary: Delete image tag + description: Permanently delete a specific image tag by ID (requires appropriate permissions) + operationId: ImageTagDeleteById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image tag deleted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ImageTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + get: + tags: + - Media + summary: Get image tag + description: Retrieve a specific image tag by ID + operationId: ImageTagGetById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + - $ref: '#/components/parameters/RenderAreas' + responses: + '200': + description: Image tag retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ImageTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + - {} # Allows unauthenticated access if publicApiProjection is defined + + patch: + tags: + - Media + summary: Update image tag + description: Partially update a specific image tag by ID using PATCH semantics + operationId: ImageTagPatchById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + title: + type: string + example: "Hero Images" + description: Tag name + slug: + type: string + example: "hero-images" + description: URL-friendly identifier + description: Only include fields to update + responses: + '200': + description: Image tag updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ImageTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + put: + tags: + - Media + summary: Replace image tag + description: Completely replace a specific image tag by ID using PUT semantics + operationId: ImageTagPutById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - title + properties: + title: + type: string + example: "Hero Images" + description: Tag name + slug: + type: string + example: "hero-images" + description: URL-friendly identifier (auto-generated if not provided) + responses: + '200': + description: Image tag replaced successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ImageTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image-tag/{_id}/dismiss-submission: + post: + tags: + - Media + summary: Dismiss image tag submission + description: Dismiss a pending submission for the specified image tag, removing it from the review queue + operationId: ImageTagDismissSubmissionById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image tag submission dismissed successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ImageTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image-tag/{_id}/locale/{toLocale}: + get: + tags: + - Media + summary: Get image tag locale + description: Retrieve the specified image tag in a specific locale + operationId: ImageTagGetLocaleById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/ToLocale' + responses: + '200': + description: Image tag locale retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ImageTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image-tag/{_id}/locales: + get: + tags: + - Media + summary: Get image tag locales + description: Retrieve all available locales for the specified image tag + operationId: ImageTagGetLocalesById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image tag locales retrieved successfully + content: + application/json: + schema: + type: array + items: + type: string + example: ["en", "es", "fr", "de"] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image-tag/{_id}/localize: + post: + tags: + - Media + summary: Localize image tag + description: Create a localized version of the specified image tag for a specific language/region + operationId: ImageTagLocalizeById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image tag localized successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ImageTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image-tag/{_id}/publish: + post: + tags: + - Media + summary: Publish image tag + description: Publish the specified image tag, making it live and visible to end users + operationId: ImageTagPublishById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image tag published successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ImageTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image-tag/{_id}/revert-draft-to-published: + post: + tags: + - Media + summary: Revert draft to published + description: Revert the draft version of the specified image tag back to its published state + operationId: ImageTagRevertDraftToPublishedById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image tag draft reverted to published successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ImageTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image-tag/{_id}/revert-published-to-previous: + post: + tags: + - Media + summary: Revert published to previous + description: Revert the published version of the specified image tag to its previous published state + operationId: ImageTagRevertPublishedToPreviousById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image tag published version reverted to previous successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ImageTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image-tag/{_id}/share: + post: + tags: + - Media + summary: Share image tag + description: Generate a sharing link or configure sharing permissions for the specified image tag + operationId: ImageTagShareById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image tag shared successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ImageTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image-tag/{_id}/submit: + post: + tags: + - Media + summary: Submit image tag + description: Submit the specified image tag for review and approval workflow + operationId: ImageTagSubmitById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image tag submitted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ImageTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/image-tag/{_id}/unpublish: + post: + tags: + - Media + summary: Unpublish image tag + description: Unpublish the specified image tag, removing it from public visibility while preserving the content + operationId: ImageTagUnpublishById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Image tag unpublished successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ImageTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + # File-tags + /@apostrophecms/file-tag: + get: + tags: + - Media + summary: List file tags + description: Retrieve a list of file tags used for organizing and categorizing uploaded files + operationId: FileTagGet + parameters: + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + - $ref: '#/components/parameters/RenderAreas' + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + results: + type: array + items: + $ref: '#/components/schemas/FileTag' + pages: + type: integer + description: Total number of pages + currentPage: + type: integer + description: Current page number + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + - {} # Allows unauthenticated access to file tags + + post: + tags: + - Media + summary: Create file tag + description: Create a new file tag for organizing uploaded files (requires editor permissions or higher) + operationId: FileTagPost + parameters: + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - title + properties: + title: + type: string + description: File tag name + example: "Documents" + description: + type: string + description: Optional description of the file tag + example: "For organizing PDF documents and text files" + color: + type: string + description: Color code for visual organization + pattern: "^#[0-9A-Fa-f]{6}$" + example: "#3498db" + responses: + '200': + description: File tag created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file-tag/archive: + post: + tags: + - Media + summary: Archive file tags + description: Archive multiple file tags, making them inactive while preserving their data + operationId: FileTagArchive + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkOperationRequest' + responses: + '200': + description: File tags archived successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/FileTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file-tag/localize: + post: + tags: + - Media + summary: Localize file tags + description: Create or update localized versions of file tags for different languages/regions + operationId: FileTagLocalize + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + _ids: + type: array + items: + type: string + description: Array of file tag IDs to localize + toLocale: + type: string + description: Target locale for localization + example: "es" + responses: + '200': + description: File tags localized successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/FileTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file-tag/publish: + post: + tags: + - Media + summary: Publish file tags + description: Publish multiple file tags, making them live and visible to end users + operationId: FileTagPublish + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + _ids: + type: array + items: + type: string + description: Array of file tag IDs to publish + responses: + '200': + description: File tags published successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/FileTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file-tag/restore: + post: + tags: + - Media + summary: Restore file tags + description: Restore previously archived file tags, making them active again + operationId: FileTagRestore + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkOperationRequest' + responses: + '200': + description: File tags restored successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/FileTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file-tag/{_id}: + delete: + tags: + - Media + summary: Delete file tag + description: Permanently delete a specific file tag by ID (requires appropriate permissions) + operationId: FileTagDeleteById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: File tag deleted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + get: + tags: + - Media + summary: Get file tag + description: Retrieve a specific file tag by ID + operationId: FileTagGetById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + responses: + '200': + description: File tag retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + - {} # Allows unauthenticated access to file tags + + patch: + tags: + - Media + summary: Update file tag + description: Partially update a specific file tag by ID using PATCH semantics + operationId: FileTagPatchById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + title: + type: string + description: File tag name + example: "Updated Documents" + description: + type: string + description: Optional description of the file tag + example: "Updated description for organizing files" + color: + type: string + description: Color code for visual organization + pattern: "^#[0-9A-Fa-f]{6}$" + example: "#e74c3c" + responses: + '200': + description: File tag updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + put: + tags: + - Media + summary: Replace file tag + description: Completely replace a specific file tag by ID using PUT semantics + operationId: FileTagPutById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - title + properties: + title: + type: string + description: File tag name + example: "Replaced Documents" + description: + type: string + description: Optional description of the file tag + example: "Completely replaced file tag description" + color: + type: string + description: Color code for visual organization + pattern: "^#[0-9A-Fa-f]{6}$" + example: "#9b59b6" + responses: + '200': + description: File tag replaced successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file-tag/{_id}/dismiss-submission: + post: + tags: + - Media + summary: Dismiss file tag submission + description: Dismiss a pending submission for the specified file tag, removing it from the review queue + operationId: FileTagDismissSubmissionById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: File tag submission dismissed successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file-tag/{_id}/locale/{toLocale}: + get: + tags: + - Media + summary: Get file tag locale + description: Retrieve the specified file tag in a specific locale + operationId: FileTagGetLocaleById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/ToLocale' + responses: + '200': + description: File tag locale retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file-tag/{_id}/locales: + get: + tags: + - Media + summary: Get file tag locales + description: Retrieve all available locales for the specified file tag + operationId: FileTagGetLocalesById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: File tag locales retrieved successfully + content: + application/json: + schema: + type: array + items: + type: string + example: ["en", "es", "fr", "de"] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file-tag/{_id}/localize: + post: + tags: + - Media + summary: Localize file tag + description: Create a localized version of the specified file tag for a specific language/region + operationId: FileTagLocalizeById + parameters: + - $ref: '#/components/parameters/DocumentId' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + toLocale: + type: string + description: Target locale for localization + example: "es" + responses: + '200': + description: File tag localized successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file-tag/{_id}/publish: + post: + tags: + - Media + summary: Publish file tag + description: Publish the specified file tag, making it live and visible to end users + operationId: FileTagPublishById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: File tag published successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file-tag/{_id}/revert-draft-to-published: + post: + tags: + - Media + summary: Revert file tag draft to published + description: Revert the draft version of the specified file tag back to its published state + operationId: FileTagRevertDraftToPublishedById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: File tag draft reverted to published successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file-tag/{_id}/revert-published-to-previous: + post: + tags: + - Media + summary: Revert file tag published to previous + description: Revert the published version of the specified file tag to its previous published state + operationId: FileTagRevertPublishedToPreviousById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: File tag published version reverted to previous successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file-tag/{_id}/share: + post: + tags: + - Media + summary: Share file tag + description: Generate a sharing link or configure sharing permissions for the specified file tag + operationId: FileTagShareById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: File tag shared successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file-tag/{_id}/submit: + post: + tags: + - Media + summary: Submit file tag + description: Submit the specified file tag for review and approval workflow + operationId: FileTagSubmitById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: File tag submitted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/file-tag/{_id}/unpublish: + post: + tags: + - Media + summary: Unpublish file tag + description: Unpublish the specified file tag, removing it from public visibility while preserving the content + operationId: FileTagUnpublishById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: File tag unpublished successfully + content: + application/json: + schema: + $ref: '#/components/schemas/FileTag' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + # Submitted-draft + /@apostrophecms/submitted-draft: + get: + tags: + - Submitted Drafts + summary: List submitted drafts + description: Retrieve a list of all submitted drafts in the review queue + operationId: SubmittedDraftGet + parameters: + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + - $ref: '#/components/parameters/RenderAreas' + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + results: + type: array + items: + $ref: '#/components/schemas/SubmittedDraft' + pages: + type: integer + description: Total number of pages available + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + post: + tags: + - Submitted Drafts + summary: Create submitted draft + description: Create a new submitted draft for review workflow (requires contributor permissions or higher) + operationId: SubmittedDraftPost + parameters: + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + title: + type: string + description: Title of the submitted draft + example: "New Article Draft" + content: + type: string + description: Content of the submitted draft + example: "This is the draft content awaiting review." + author: + type: string + description: Author of the submitted draft + example: "John Doe" + submissionNotes: + type: string + description: Notes from the submitter about the draft + example: "Please review for accuracy and tone." + priority: + type: string + enum: [low, normal, high, urgent] + default: normal + description: Priority level for review + category: + type: string + description: Category or type of content being submitted + example: "blog-post" + responses: + '200': + description: Submitted draft created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SubmittedDraft' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/submitted-draft/archive: + post: + tags: + - Submitted Drafts + summary: Archive submitted drafts + description: Archive multiple submitted drafts, removing them from active review queues while preserving data + operationId: SubmittedDraftArchive + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkOperationRequest' + responses: + '200': + description: Submitted drafts archived successfully + content: + application/json: + schema: + type: object + properties: + archived: + type: array + items: + $ref: '#/components/schemas/SubmittedDraft' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + + /@apostrophecms/submitted-draft/localize: + post: + tags: + - Submitted Drafts + summary: Localize submitted drafts + description: Create or update localized versions of submitted drafts for different languages/regions + operationId: SubmittedDraftLocalize + responses: + '200': + description: Submitted drafts localized successfully + content: + application/json: + schema: + type: object + properties: + localized: + type: array + items: + $ref: '#/components/schemas/SubmittedDraft' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + + /@apostrophecms/submitted-draft/publish: + post: + tags: + - Submitted Drafts + summary: Publish submitted drafts + description: Bulk publish multiple submitted drafts, moving them from draft status to published content + operationId: SubmittedDraftPublish + responses: + '200': + description: Submitted drafts published successfully + content: + application/json: + schema: + type: object + properties: + published: + type: array + items: + $ref: '#/components/schemas/SubmittedDraft' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + + /@apostrophecms/submitted-draft/restore: + post: + tags: + - Submitted Drafts + summary: Restore submitted drafts + description: Restore previously archived submitted drafts, returning them to active review queues + operationId: SubmittedDraftRestore + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkOperationRequest' + responses: + '200': + description: Submitted drafts restored successfully + content: + application/json: + schema: + type: object + properties: + restored: + type: array + items: + $ref: '#/components/schemas/SubmittedDraft' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + $ref: '#/components/responses/InternalServerError' + + /@apostrophecms/submitted-draft/{_id}: + delete: + tags: + - Submitted Drafts + summary: Delete submitted draft + description: Permanently delete a specific submitted draft by ID (requires appropriate permissions) + operationId: SubmittedDraftDeleteById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Submitted draft deleted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SubmittedDraft' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + + get: + tags: + - Submitted Drafts + summary: Get submitted draft + description: Retrieve a specific submitted draft by ID (requires appropriate permissions) + operationId: SubmittedDraftGetById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Submitted draft retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SubmittedDraft' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + + patch: + tags: + - Submitted Drafts + summary: Update submitted draft + description: Partially update a specific submitted draft by ID using PATCH semantics + operationId: SubmittedDraftPatchById + parameters: + - $ref: '#/components/parameters/DocumentId' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + title: + type: string + description: Updated title of the submitted draft + content: + type: string + description: Updated content of the submitted draft + submissionNotes: + type: string + description: Updated notes about the submission + priority: + type: string + enum: [low, normal, high, urgent] + description: Updated priority level for review + responses: + '200': + description: Submitted draft updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SubmittedDraft' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + put: + tags: + - Submitted Drafts + summary: Replace submitted draft + description: Completely replace a specific submitted draft by ID using PUT semantics + operationId: SubmittedDraftPutById + parameters: + - $ref: '#/components/parameters/DocumentId' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + title: + type: string + description: Title of the submitted draft + example: "Updated Article Draft" + content: + type: string + description: Content of the submitted draft + example: "This is the updated draft content." + author: + type: string + description: Author of the submitted draft + example: "John Doe" + submissionNotes: + type: string + description: Notes about the submission + example: "Updated after initial feedback." + priority: + type: string + enum: [low, normal, high, urgent] + default: normal + description: Priority level for review + required: + - title + - content + responses: + '200': + description: Submitted draft replaced successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SubmittedDraft' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + + /@apostrophecms/submitted-draft/{_id}/dismiss-submission: + post: + tags: + - Submitted Drafts + summary: Dismiss submission + description: Dismiss a pending submission for the specified draft, removing it from the review queue + operationId: SubmittedDraftDismissSubmissionById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Submission dismissed successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SubmittedDraft' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + + /@apostrophecms/submitted-draft/{_id}/locale/{toLocale}: + get: + tags: + - Submitted Drafts + summary: Get submitted draft locale + description: Retrieve the specified submitted draft in a specific locale + operationId: SubmittedDraftGetLocaleById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/ToLocale' + responses: + '200': + description: Submitted draft locale retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SubmittedDraft' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + + /@apostrophecms/submitted-draft/{_id}/locales: + get: + tags: + - Submitted Drafts + summary: Get submitted draft locales + description: Retrieve all available locales for the specified submitted draft + operationId: SubmittedDraftGetLocalesById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Submitted draft locales retrieved successfully + content: + application/json: + schema: + type: array + items: + type: string + example: ["en", "es", "fr", "de"] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + + /@apostrophecms/submitted-draft/{_id}/localize: + post: + tags: + - Submitted Drafts + summary: Localize submitted draft + description: Create a localized version of the specified submitted draft for a specific language/region + operationId: SubmittedDraftLocalizeById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Submitted draft localized successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SubmittedDraft' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + + /@apostrophecms/submitted-draft/{_id}/publish: + post: + tags: + - Submitted Drafts + summary: Publish submitted draft + description: Publish the specified submitted draft, moving it from draft status to published content + operationId: SubmittedDraftPublishById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Submitted draft published successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SubmittedDraft' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + + /@apostrophecms/submitted-draft/{_id}/revert-draft-to-published: + post: + tags: + - Submitted Drafts + summary: Revert draft to published + description: Revert the draft version of the specified submitted draft back to its published state + operationId: SubmittedDraftRevertDraftToPublishedById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Draft reverted to published successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SubmittedDraft' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + + /@apostrophecms/submitted-draft/{_id}/revert-published-to-previous: + post: + tags: + - Submitted Drafts + summary: Revert published to previous + description: Revert the published version of the specified submitted draft to its previous published state + operationId: SubmittedDraftRevertPublishedToPreviousById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Published version reverted to previous successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SubmittedDraft' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + + /@apostrophecms/submitted-draft/{_id}/share: + post: + tags: + - Submitted Drafts + summary: Share submitted draft + description: Generate a sharing link or configure sharing permissions for the specified submitted draft + operationId: SubmittedDraftShareById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Submitted draft shared successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SubmittedDraft' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + + /@apostrophecms/submitted-draft/{_id}/submit: + post: + tags: + - Submitted Drafts + summary: Submit draft + description: Submit the specified draft for review and approval workflow + operationId: SubmittedDraftSubmitById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Draft submitted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SubmittedDraft' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + + /@apostrophecms/submitted-draft/{_id}/unpublish: + post: + tags: + - Submitted Drafts + summary: Unpublish submitted draft + description: Unpublish the specified submitted draft, removing it from public visibility while preserving the content + operationId: SubmittedDraftUnpublishById + parameters: + - $ref: '#/components/parameters/DocumentId' + responses: + '200': + description: Submitted draft unpublished successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SubmittedDraft' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + + #Attachments + /@apostrophecms/attachment/upload: + post: + tags: + - Attachments + summary: Upload media file + description: | + Upload a media file to create an attachment. The uploaded file can then be used + to create image or file documents. Uses multipart/form-data encoding with the + file uploaded under the name 'file'. + operationId: AttachmentUpload + parameters: + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + required: + - file + properties: + file: + type: string + format: binary + description: The file to upload + encoding: + file: + contentType: image/*, application/pdf, application/*, text/* + responses: + '200': + description: File uploaded successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Attachment' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '413': + description: File too large + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '415': + description: Unsupported file type + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/attachment/crop: + post: + tags: + - Attachments + summary: Crop image attachment + description: | + Create a cropped version of an existing image attachment. The crop object + is appended to the crops array property of the attachment document. + The newly uploaded image file will be stored with a filename using the + crop properties: {_id}-{name}.{top}.{left}.{width}.{height}.{extension} + operationId: AttachmentCrop + parameters: + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - _id + - crop + properties: + _id: + type: string + description: The _id property of an existing image attachment document + example: "ckj0akbxa003vp39kfbxgb8zg" + crop: + type: object + description: Crop coordinates and dimensions + required: + - top + - left + - width + - height + properties: + top: + type: integer + description: Top coordinate of the crop area (pixels) + example: 10 + minimum: 0 + left: + type: integer + description: Left coordinate of the crop area (pixels) + example: 15 + minimum: 0 + width: + type: integer + description: Width of the crop area (pixels) + example: 300 + minimum: 1 + height: + type: integer + description: Height of the crop area (pixels) + example: 200 + minimum: 1 + responses: + '200': + description: Image cropped successfully + content: + application/json: + schema: + type: boolean + example: true + description: Returns true on successful crop + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '422': + description: Unprocessable entity - crop coordinates exceed image bounds + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + # i18n + /@apostrophecms/i18n/locales: + get: + tags: + - Internationalization + summary: Get all configured locales + description: | + Returns information about all configured locales including labels and edit permissions. + Authentication is required to access locale configuration data. + operationId: I18nLocalesGet + responses: + '200': + description: Locales retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/LocalesResponse' + example: + en: + label: "English" + _edit: true + fr: + label: "French" + _edit: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/i18n/locale: + post: + tags: + - Internationalization + summary: Get locale path and manage clipboard + description: | + Returns the path to a locale home-page or optional document and makes the clipboard + available in the given locale. Used for cross-locale navigation. + parameters: + - name: contextDocId + in: query + description: Optional document ID for the path, defaults to locale home-page + required: false + schema: + type: string + example: "cloydg3ka0005qcls5vmg8sb9" + - name: locale + in: query + description: Required. The locale for the desired path + required: true + schema: + type: string + example: "fr" + - name: clipboard + in: query + description: Optional clipboard content for cross-domain situations + required: false + schema: + type: string + example: "exampleClipboardContent" + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/LocaleRequest' + examples: + basic_locale_switch: + summary: Basic locale switch to home page + value: + locale: "fr" + with_context_doc: + summary: Switch locale for specific document + value: + locale: "fr" + contextDocId: "cloydg3ka0005qcls5vmg8sb9" + with_clipboard: + summary: Cross-domain switch with clipboard + value: + locale: "fr" + contextDocId: "cloydg3ka0005qcls5vmg8sb9" + clipboard: "exampleClipboardContent" + operationId: I18nLocalePost + responses: + '200': + description: Locale path retrieved successfully + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/SameHostnameResponse' + - $ref: '#/components/schemas/DifferentHostnameResponse' + examples: + same_hostname: + summary: Same hostname response + value: + redirectTo: "/fr/page-slug" + different_hostname: + summary: Different hostname response + value: + redirectTo: "https://fr.example.com/french-example-page?aposCrossDomainSessionToken=generated_token" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/i18n/exist-in-locale: + post: + tags: + - Internationalization + summary: Check document existence in locale + description: | + Returns arrays of original document IDs, new locale IDs, and aposDocIds + for an array of document IDs in a specified locale and mode. + parameters: + - name: ids + in: query + description: Required. Array of document IDs to check in the specified locale + required: true + schema: + type: array + items: + type: string + example: ["cloydg3ka0005qcls5vmg8sb9", "cloydg3ka0005qcls5vmg8sb8"] + - name: locale + in: query + description: Required. The locale in which to check for the document IDs + required: true + schema: + type: string + example: "fr" + - name: mode + in: query + description: Required. The mode (draft or published) in which to check for the document IDs + required: true + schema: + type: string + enum: [draft, published] + example: "published" + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ExistInLocaleRequest' + example: + ids: ["cloydg3ka0005qcls5vmg8sb9", "cloydg3ka0005qcls5vmg8sb8"] + locale: "fr" + mode: "published" + operationId: I18nExistsPost + responses: + '200': + description: Document existence check completed successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ExistInLocaleResponse' + example: + originalLocaleIds: ["cloydg3ka0005qcls5vmg8sb9:en:published", "cloydg3ka0005qcls5vmg8sb8:en:published"] + newLocaleIds: ["cloydg3ka0005qcls5vmg8sb9:fr:published", "cloydg3ka0005qcls5vmg8sb8:fr:published"] + aposDocIds: ["cloydg3ka0005qcls5vmg8sb9", "cloydg3ka0005qcls5vmg8sb8"] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] diff --git a/docs/reference/api/api-explorer.md b/docs/reference/api/api-explorer.md new file mode 100644 index 00000000..c90969be --- /dev/null +++ b/docs/reference/api/api-explorer.md @@ -0,0 +1,209 @@ +--- +title: ApostropheCMS API Explorer - Interactive Testing +description: Test ApostropheCMS REST API endpoints interactively with live authentication +--- + +# API Explorer + +The API Explorer lets you test ApostropheCMS REST API endpoints directly in your browser with real authentication. Connect to your local development server or a live instance to experiment with requests and see actual responses. + +## When to Use the Explorer vs Documentation + +**Use the API Explorer when you want to:** +- Test endpoints with your actual project data +- Experiment with query parameters and request bodies +- Validate authentication configuration +- Generate curl commands for debugging +- Quickly verify an endpoint's behavior + +**Use the [written API documentation](rest-api-reference) when you want to:** +- Learn API patterns and best practices +- Understand field formats and data structures +- Copy code examples into your application +- Read detailed explanations of endpoints +- Work offline or on mobile + +> **π‘ Testing with Localhost**: This explorer can connect to a project running at `localhost:3000` on your workstation to test standard API routes. You can test with API key or bearer token authentication, but not session cookies. + +--- + +## Before you start + +To use this page as an interactive testing environment: + +1. **Start your Apostrophe project** + + ```bash + npm run dev + # or + node app + ``` + + Make sure it is reachable at: + + - `http://localhost:3000` (default ApostropheCMS dev port) + +2. **Scroll to the server URL in the spec** + + In the sidebar, the [`Interactive Explorer`](#π½-interactive-explorer) is marked with an icon. In the Swagger UI, you will find the **Server** dropdown near the top. It should show something like: + + - `http://localhost:3000` + +3. **Click the `Authorize` button** + - See more below about authorization steps. +--- + +## Step-by-step: Authorize and run your first request + +Swagger UI will happily send anonymous requests, but most Apostrophe endpoints require authentication. + +Follow these steps carefully: + +1. **Click the green "Authorize" button** + +2. **Choose an auth method** + + The dialog lists three security schemes. + + - `ApiKeyAuth` + - `BearerAuth` + - `SessionAuth` + +3. **Recommended: start with API key auth** + + - In your project, typically in the `modules/@apostrophecms/express/index.js` file, add an API key: + ``` js + export default { + options: { + session: { + secret: 'myProjectSecret' + }, + apiKeys: { + mysecretapikey: { + role: 'admin' + } + } + } + }; + ``` + - In the **Authorize** dialog of the explorer, scroll up to find the **API key** entry. + - Paste your API key into the value field - in this example, `mysecretapikey`. + - Click **Authorize**. + - Then click **Close** at the bottom of the dialog. + > [!NOTE] + > You will not get any message regarding the validity of the key. If your endpoint requests fail with a `404` error, you likely entered the key wrong. Logout from the API key authorization section and reenter the key. + +4. **Try a simple GET request** +  + + - Expand a simple GET endpoint (for example, the first "Users" route). + - Click the route to expand it + - Click **Try it out** + - Change any of the parameters if desired + - Click **Execute** + - Check the **Response** section below the request: + - Status `200` or `201` = success + - Status `401`, `403` or `404` = auth problem; double-check your API key. + +--- + +## Alternative: Bearer token via login route (more steps) + +If you prefer to log in with a username/password instead of using an API key, you can: + +1. **Find the login route** + + - In the explorer, look for the login endpoint (`POST` with `/@apostrophecms/login/login`). + - Expand that operation. + +2. **Send a login request** + + - Click **Try it out**. + - In the request body, edit the `username` and `password` values. + - Click **Execute**. + +3. **Copy the token from the response** + + - In the **Responses**, scroll down to the `200` response. + - Manually copy the token value, not including the quotes. The copy button will copy both the key and value. + +4. **Configure Bearer auth in Swagger UI** + + - Click the **Authorize** button at the top of the Swagger UI. + - Find the **BearerAuth** input. + - Paste **only** the token value into the field (Swagger UI will add `Bearer ` for you). + - Click **Authorize**, then **Close**. + +5. **Try a simple GET request** +  + + - Expand a simple GET endpoint (for example, the first "Users" route). + - Click the route to expand it + - Click **Try it out** + - Change any of the parameters if desired + - Click **Execute** + - Check the **Response** section below the request: + - Status `200` or `201` = success + - Status `401`, `403` or `404` = auth problem; double-check your token. + +--- + +## Why session cookie auth is not supported here + +ApostropheCMS typically uses a session cookie (for example, `project-shortname.sid`) when you log into the admin UI. The online Swagger explorer **cannot** reuse that login, because: + +- The in-documentation Swagger UI runs in your browser as a separate web app. +- It cannot safely or portably access cookies from another origin. +- Even if it could, CORS rules usually block cross-site cookie usage. + +Because of this, you **cannot** use the "Authorize" dialog to test "I'm logged into the admin UI" style session behavior. For cookie-based flows: + +- Download the [OpenAPI spec file repo](https://github.com/apostrophecms/apostrophecms-openapi) and set it up locally +- Use an API client like Postman/Insomnia and configure cookie handling there. + +The interactive explorer on this page is intentionally focused on **header-based authentication**: API keys and bearer tokens. + +--- + +## π½ Interactive Explorer + +Below is the full Swagger UI. +Once your server is running and you follow the authorization instructions, use `Try it out β Execute` in each endpoint to test. + +