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 website!

+ _id: + type: string + example: widget-id-123 + seoFields: + type: object + description: SEO metadata for the page + properties: + metaDescription: + type: string + description: Meta description for search engines + maxLength: 160 + example: Learn about our company, mission, and values + metaKeywords: + type: string + description: Meta keywords (legacy, rarely used) + example: about, company, mission + ogTitle: + type: string + description: Open Graph title for social sharing + example: About Our Company + ogDescription: + type: string + description: Open Graph description for social sharing + example: Discover our story and what drives us forward + ogImage: + type: object + description: Open Graph image for social sharing + properties: + _id: + type: string + example: image-id-456 + title: + type: string + example: Company Photo + attachment: + type: object + properties: + _id: + type: string + example: attachment-789 + name: + type: string + example: company-photo + extension: + type: string + example: jpg + _url: + type: string + example: /uploads/attachments/company-photo.jpg + _ancestors: + type: array + description: Array of ancestor page IDs in the page tree hierarchy + items: + type: string + example: + - root-page-id + _children: + type: array + description: Array of child pages (when requested with children parameter) + items: + $ref: '#/components/schemas/Page' + example: [] + _url: + type: string + description: Full URL to the page + example: https://example.com/about-us + format: uri + _edit: + type: boolean + description: Whether current user can edit this page + example: true + _publish: + type: boolean + description: Whether current user can publish this page + example: true + _publishedDoc: + allOf: + - $ref: '#/components/schemas/Page' + - description: Published version of the page (when viewing drafts) + _draftDoc: + allOf: + - $ref: '#/components/schemas/Page' + - description: Draft version of the page (when viewing published) + required: + - _id + - aposDocId + - type + - title + - slug + - path + - level + additionalProperties: true + example: + _id: ckhdscx5900054z9k88uqs16w:en:published + aposDocId: ckhdscx5900054z9k88uqs16w + aposLocale: en + aposMode: published + archived: false + createdAt: '2023-01-15T10:30:00.000Z' + updatedAt: '2024-12-18T14:20:00.000Z' + titleSortified: about us + slug: /about-us + path: /about-us + rank: 0 + level: 1 + orphan: false + parked: [] + visibility: public + type: '@apostrophecms/page' + title: About Us + main: + metaType: area + items: + - metaType: widget + type: '@apostrophecms/rich-text' + aposPlaceholder: false + content:

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=`. + AposArea: + type: object + additionalProperties: false + properties: + items: + type: array + items: + $ref: '#/components/schemas/Widget' + required: + - items + description: | + The value saved on the doc: an object with an `items` array of widgets. + # --- Data value (what’s stored on the doc) --- + AposAttachment: + type: object + description: | + Attachment metadata saved on the document. + Extra fields maybe present depending on project config and file type (e.g., image dimensions). + additionalProperties: true + properties: + _id: + type: string + description: Internal id of the uploaded file. + name: + type: string + description: Basename without extension. + extension: + type: string + description: File extension (e.g., "pdf", "png"). + mimeType: + type: string + description: MIME type (e.g., "application/pdf", "image/png"). + group: + type: string + description: Broad file group (e.g., "images", "office", "video", "audio", + "generic"). + size: + type: integer + description: File size in bytes. + width: + type: integer + description: Image width in pixels (if applicable). + height: + type: integer + description: Image height in pixels (if applicable). + required: + - _id + AposRelationship: + description: | + The stored value of a relationship field. For multi-select joins,this is an array of entries. + For `max: 1`, treat it as either a single entry or null. + An entry always contains at least the related `_id`; additional keys may appear if `fields` were defined. + oneOf: + - $ref: '#/components/schemas/RelationshipEntry' + - type: 'null' + - type: array + items: + $ref: '#/components/schemas/RelationshipEntry' + AposRelationshipReverse: + type: array + items: + $ref: '#/components/schemas/RelationshipEntry' + description: Populated reverse relationships at read time. Not persistedon this document; useful in responses. + AposObjectId: + type: string + pattern: ^[a-fA-F0-9]{24}$ + description: MongoDB ObjectId (24 hex chars) + AposObjectIdArray: + type: array + items: + $ref: '#/components/schemas/AposPrimitives/$defs/AposObjectId' + AposJSON: + type: object + additionalProperties: true + AposJSONArray: + type: array + items: + $ref: '#/components/schemas/AposPrimitives/$defs/AposJSON' + NullableString: + type: + - string + - 'null' + NullableInteger: + type: + - integer + - 'null' + NullableNumber: + type: + - number + - 'null' + NullableBoolean: + type: + - boolean + - 'null' + NullableObjectId: + type: + - string + - 'null' + pattern: ^[a-fA-F0-9]{24}$ + title: AposPrimitives + + responses: + BadRequest: + description: Bad request - invalid input parameters + content: + application/json: + schema: + type: object + properties: + error: + type: string + example: "Invalid request parameters" + message: + type: string + example: "The request could not be processed due to invalid input" + + Unauthorized: + description: Authentication required + content: + application/json: + schema: + type: object + properties: + error: + type: string + example: "Unauthorized" + message: + type: string + example: "Authentication is required to access this resource" + + Forbidden: + description: Access forbidden - insufficient permissions + content: + application/json: + schema: + type: object + properties: + error: + type: string + example: "Forbidden" + message: + type: string + example: "You do not have permission to perform this action" + + NotFound: + description: Resource not found + content: + application/json: + schema: + type: object + properties: + error: + type: string + example: "Not Found" + message: + type: string + example: "The requested resource could not be found" + + InternalServerError: + description: Internal server error + content: + application/json: + schema: + type: object + properties: + error: + type: string + example: "Internal Server Error" + message: + type: string + example: "An unexpected error occurred while processing the request" + + PieceOperationSuccess: + description: Operation completed successfully + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + message: + type: string + example: "Operation completed successfully" + +paths: + # Authentication endpoints + /@apostrophecms/login/login: + post: + tags: + - Authentication + summary: "Login to get authentication token" + description: | + πŸš€ **Start here!** Authenticate and receive either a bearer token or session cookie for subsequent API requests. + + **Perfect for:** + - Getting started with the API + - Setting up authentication for your app + - Testing API access + + **Choose your authentication method:** + - **Bearer Token** (recommended): omit `session` field or set to `false` + - **Session Cookie**: set `session` to `true` and include `credentials: 'include'` in fetch + operationId: AuthLogin + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - username + - password + properties: + username: + type: string + description: User's login username + example: "admin" + password: + type: string + format: password + description: User's password + session: + type: boolean + description: Set to true to receive session cookie instead of bearer token + default: false + example: false + examples: + bearer_token: + summary: "Request bearer token (recommended)" + value: + username: "admin" + password: "your-password" + session_cookie: + summary: "Request session cookie" + value: + username: "admin" + password: "your-password" + session: true + responses: + '200': + description: Login successful + content: + application/json: + schema: + type: object + properties: + token: + type: string + description: Bearer token (only present when session is false/omitted) + example: "random123Token456xyz" + examples: + bearer_response: + summary: "Bearer token response" + value: + token: "random123Token456xyz" + session_response: + summary: "Session cookie response (token field not present)" + value: {} + headers: + Set-Cookie: + description: Session cookie (only when session=true) + schema: + type: string + example: "apostrophe.sid=s%3A...; Path=/; HttpOnly" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalServerError' + security: [] + + /@apostrophecms/login/logout: + post: + tags: + - Authentication + summary: "Logout and invalidate session" + description: | + End the current session or invalidate the bearer token. + + **For bearer token**: include Authorization header + **For session cookie**: include credentials in request + operationId: AuthLogout + responses: + '200': + description: Logout successful + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/login/reset-request: + post: + tags: + - Authentication + summary: "Request password reset" + description: | + Initiates a password reset process by sending a reset link to the user's email address. + + **⚠️ Note:** This endpoint is only available when `passwordReset` is enabled in the login module configuration. + + **Security feature:** The user will not be notified if the email check fails or if the email fails to send. + However, debug information will be output in the server terminal. + operationId: AuthResetRequest + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - email + properties: + email: + type: string + format: email + description: Email address of the user requesting password reset + example: "user@example.com" + responses: + '200': + description: Password reset request processed (always returns success for security) + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + message: + type: string + example: "If an account with that email exists, a password reset link has been sent." + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: [] + + /@apostrophecms/login/reset: + post: + tags: + - Authentication + summary: "Complete password reset" + description: | + Completes a password reset using the token provided in the reset email. + + **⚠️ Note:** This endpoint is only available when `passwordReset` is enabled in the login module configuration. + + Reset tokens are valid for the number of hours specified in `passwordResetHours` (default: 48 hours). + operationId: AuthReset + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - token + - password + properties: + token: + type: string + description: Reset token from the password reset email + example: "reset-token-from-email" + password: + type: string + format: password + description: New password for the user account + example: "new-secure-password" + responses: + '200': + description: Password reset completed successfully + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + message: + type: string + example: "Password has been reset successfully" + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '410': + description: Reset token expired + content: + application/json: + schema: + type: object + properties: + error: + type: string + example: "Reset token has expired" + '500': + $ref: '#/components/responses/InternalServerError' + security: [] + + /@apostrophecms/login/whoami: + get: + tags: + - Authentication + summary: "Get current user information" + deprecated: true + description: | + **⚠️ DEPRECATED:** This GET endpoint is deprecated due to caching issues. + Use the POST method instead. + + Returns information about the currently authenticated user. + + **Security note:** Only explicitly configured fields are returned, + never the complete user object. This prevents accidental exposure + of sensitive user data. + operationId: AuthWhoAmI + responses: + '200': + description: Current user information retrieved successfully + content: + application/json: + schema: + type: object + properties: + _id: + type: string + description: User's unique identifier + example: "user123" + username: + type: string + description: User's login username + example: "john-doe" + title: + type: string + description: User's display name + example: "John Doe" + email: + type: string + format: email + description: User's email address (if configured in whoamiFields) + example: "john@example.com" + additionalProperties: true + description: Additional fields based on whoamiFields configuration + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + post: + tags: + - Authentication + summary: "Get current user information" + description: | + Returns information about the currently authenticated user. + + **Note:** POST method is recommended for this endpoint to avoid caching issues. + + **Perfect for:** + - Checking if authentication is working + - Getting user details for your app + - Validating permissions + + **Security note:** Only explicitly configured fields are returned, + never the complete user object. This prevents accidental exposure + of sensitive user data. + operationId: AuthWhoAmIPost + responses: + '200': + description: Current user information retrieved successfully + content: + application/json: + schema: + type: object + properties: + _id: + type: string + description: User's unique identifier + example: "user123" + username: + type: string + description: User's login username + example: "john-doe" + title: + type: string + description: User's display name + example: "John Doe" + email: + type: string + format: email + description: User's email address (if configured in whoamiFields) + example: "john@example.com" + additionalProperties: true + description: Additional fields based on whoamiFields configuration + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + /@apostrophecms/login/context: + get: + tags: + - Authentication + summary: "Get login context information" + deprecated: true + description: | + **⚠️ DEPRECATED:** This GET endpoint is deprecated due to caching issues. + Use the POST method instead. + + Returns login context information including environment and requirements. + This endpoint provides information about the login system configuration. + + **Useful for:** + - Understanding available login methods + - Checking if password reset is enabled + - Getting login system configuration + operationId: AuthContext + responses: + '200': + description: Login context retrieved successfully + content: + application/json: + schema: + type: object + properties: + localLogin: + type: boolean + description: Whether local login is enabled + example: true + passwordReset: + type: boolean + description: Whether password reset is enabled + example: false + loginUrl: + type: string + description: The configured login URL + example: "/login" + additionalProperties: true + description: Additional context based on configuration + '400': + $ref: '#/components/responses/BadRequest' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + post: + tags: + - Authentication + summary: "Get login context information" + description: | + Returns login context information including environment and requirements. + This endpoint provides information about the login system configuration. + + **Note:** POST method is recommended for this endpoint to avoid caching issues. + + **Useful for:** + - Understanding available login methods + - Checking if password reset is enabled + - Getting login system configuration + operationId: AuthContextPost + responses: + '200': + description: Login context retrieved successfully + content: + application/json: + schema: + type: object + properties: + localLogin: + type: boolean + description: Whether local login is enabled + example: true + passwordReset: + type: boolean + description: Whether password reset is enabled + example: false + loginUrl: + type: string + description: The configured login URL + example: "/login" + additionalProperties: true + description: Additional context based on configuration" + '400': + $ref: '#/components/responses/BadRequest' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + - SessionAuth: [] + + # Page endpoints + /@apostrophecms/page: + get: + tags: + - Pages + summary: Get page tree + description: | + πŸš€ **Essential for headless sites!** Fetch your site's complete page structure and content. + + **Perfect for:** + - Building navigation menus + - Getting all pages for static site generation + - Fetching content for SPA routing + - Understanding your site structure + + Returns the complete page hierarchy starting from the home page. Use `flat=1` to get pages in a flat array instead of nested structure. + operationId: PageGet + parameters: + - $ref: '#/components/parameters/AllPages' + - $ref: '#/components/parameters/FlatResponse' + - $ref: '#/components/parameters/ChildrenParam' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + responses: + '200': + description: Page tree retrieved successfully + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/PageTreeResponse' + - $ref: '#/components/schemas/FlatPageResponse' + examples: + tree_response: + summary: Nested page tree (default) + value: + _id: "ckhdscx5900054z9k88uqs16w" + title: "Home Page" + slug: "/" + type: "@apostrophecms/home-page" + _children: [] + flat_response: + summary: Flat array response (with flat=1) + value: + 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: [] + - {} + + post: + tags: + - Pages + summary: Create new page + description: | + Insert a new page at the specified position in the page tree. + + **Perfect for:** + - Programmatically creating pages + - Building page management interfaces + - Migrating content from other systems + + Requires `_targetId` and `_position` to determine placement in the page tree. + operationId: PagePost + parameters: + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PageCreateRequest' + examples: + new_page: + summary: Create new page as first child + value: + title: "New Page" + _targetId: "ckhdscx5900054z9k88uqs16w" + _position: "firstChild" + copy_page: + summary: Create page by copying existing one + value: + title: "Copied Page" + _targetId: "_home" + _position: "lastChild" + _copyingId: "existing-page-id" + responses: + '200': + description: Page created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Page' + '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/page/archive: + post: + tags: + - Pages + summary: Archive pages + description: Archive pages in bulk, making them inactive while preserving their data in the page tree + operationId: PageArchive + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + _ids: + type: array + items: + type: string + description: Array of page IDs to archive + example: ["page1-id", "page2-id"] + 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/page/localize: + post: + tags: + - Pages + summary: Localize pages + description: Create or update localized versions of pages in bulk for different languages/regions + operationId: PageLocalize + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + _ids: + type: array + items: + type: string + description: Array of page IDs to localize + example: ["page1-id", "page2-id"] + toLocale: + type: string + description: Target locale for localization + example: "es" + responses: + '200': + description: Pages localized successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Page' + '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/page/publish: + post: + tags: + - Pages + summary: Publish pages + description: Publish pages in bulk, making them live and visible to end users in the page tree + operationId: PagePublish + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + _ids: + type: array + items: + type: string + description: Array of page IDs to publish + example: ["page1-id", "page2-id"] + responses: + '200': + description: Pages published successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Page' + '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/page/restore: + post: + tags: + - Pages + summary: Restore pages + description: Restore previously archived pages in bulk, making them active again in the page tree + operationId: PageRestore + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkOperationRequest' + responses: + '200': + description: Pages restored successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Page' + '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/page/{_id}: + delete: + tags: + - Pages + summary: Delete page + description: | + ⚠️ **Permanently delete a page document.** This cannot be undone. + + **Important**: This endpoint should be used to delete the draft version of a page. If the page has been published, you should unpublish it first using the unpublish endpoint + to ensure complete removal. + + **Recommended deletion workflow**: + 1. Unpublish the page (removes published version) + 2. Delete the page (removes draft version) + + **Restrictions:** + - Cannot delete home page + - Cannot delete pages with children (delete children first) + - Cannot delete draft if published version exists + ⚠️ **Permanently delete a page document.** This cannot be undone. + + **Use with caution!** + operationId: PageDeleteById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + responses: + '200': + description: Page deleted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Page' + '400': + description: Deletion not allowed + content: + application/json: + schema: + type: object + properties: + name: + type: string + example: "invalid" + data: + type: object + message: + type: string + example: "You must delete the children of this page first." + '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: + - Pages + summary: Get page by ID + description: | + Fetch a single page document by ID for detailed content access. + + **Perfect for:** + - Getting page content for rendering + - Fetching specific page data + - Building page detail views + + The ID can include mode and locale (e.g., `id:en:published`) or use query parameters to specify them. + operationId: PageGetById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + - $ref: '#/components/parameters/RenderAreas' + responses: + '200': + description: Page 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: [] + - {} + + patch: + tags: + - Pages + summary: Update page + description: | + Partially update a page document. + + **Perfect for:** + - Updating page titles or content + - Moving pages within the tree + - Making incremental changes + + Can use MongoDB-style operators and dot notation for nested properties. Include `_targetId` and `_position` to move the page within the tree. + operationId: PagePatchById + parameters: + - $ref: '#/components/parameters/DocumentId' + - $ref: '#/components/parameters/AposMode' + - $ref: '#/components/parameters/AposLocale' + requestBody: + required: true + content: + application/json: + schema: + anyOf: + - $ref: '#/components/schemas/PageUpdateRequest' + - $ref: '#/components/schemas/PageDotNotationUpdate' + examples: + update_title: + summary: Update page title only + value: + title: "Updated Page Title" + move_page: + summary: Move page to new position + value: + _targetId: "target-page-id" + _position: "after" + archive_page: + summary: Move page to archive + value: + _targetId: "_archive" + _position: "lastChild" + dot_notation: + summary: Update nested content with dot notation + value: + "description.items.0.content": "

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** + ![The 'Get Users' GET endpoint in the Swagger UI](../../images/swagger-user-endpoint.png) + + - 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** +![The Swagger UI POST login route endpoint selector](../../images/swagger-login-route.png) + - 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** + ![The 'Get Users' GET endpoint in the Swagger UI](../../images/swagger-user-endpoint.png) + + - 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. + + + +--- + +## Need More Detail? + +The API Explorer shows you what each endpoint does, but for deeper understanding: + +- **[API Documentation Home](/reference/api/rest-api-reference)** - Overview and getting started +- **[Authentication Guide](/reference/api/authentication)** - Detailed auth setup +- **[Piece Type API](/reference/api/pieces)** - Working with content types +- **[Page Type API](/reference/api/pages)** - Managing pages and navigation +- **[Field Formats](/reference/api/field-formats)** - Understanding response structures + +--- + +## Testing Against Your Own Site + +For testing against deployed sites or more advanced workflows: + +1. **Download**: Get our [OpenAPI specification](/openapi.yaml){download="apostrophecms-openapi.yaml"} or the [full repo](https://github.com/apostrophecms/apostrophecms-openapi). +2. **Import**: Load it into Postman, Insomnia, or similar tools if not using the repo +3. **Configure**: Set your server URL and authentication token + - Server URL (change `https://your-site.com` to your actual domain) + - Session cookie name (change `project-shortname.sid` to `yourproject.sid`) +4. **Test**: Make live API calls to your ApostropheCMS instance, either locally or your hosted site + +## About This Reference + +This interactive documentation is generated from our [OpenAPI specification](/apostrophecms-openapi.yaml). You can: + +- **Test endpoints live**: Make real API calls to your locally running project (with authentication) +- **View request/response examples**: See exactly what data to send and expect +- **Understand schemas**: Explore all data models and field requirements +- **Copy code samples**: Get ready-to-use code + +For more guidance, see our [`apostrophecms-openapi` repo](https://github.com/apostrophecms/apostrophecms-openapi). \ No newline at end of file diff --git a/docs/reference/api/rest-api-reference.md b/docs/reference/api/rest-api-reference.md new file mode 100644 index 00000000..0dc22408 --- /dev/null +++ b/docs/reference/api/rest-api-reference.md @@ -0,0 +1,209 @@ +--- +title: ApostropheCMS REST API Reference +description: Complete REST API documentation for ApostropheCMS headless CMS +next: + text: 'Authentication' + link: '/reference/api/authentication.html' +--- + +# ApostropheCMS REST API + +ApostropheCMS provides a comprehensive REST API for headless CMS functionality, enabling you to build modern applications with any frontend framework while managing content through Apostrophe's intuitive editing experience. + +## Getting Started + +The REST API gives you programmatic access to all your content and media: + +- **Content Management**: Create, read, update, and delete pages and pieces +- **Media Operations**: Upload, crop, and organize images and files +- **Multilingual Support**: Manage content across multiple locales +- **Flexible Authentication**: API keys for server-to-server, bearer tokens for client apps + +### Quick Start + +All API endpoints follow RESTful conventions and return JSON responses. Most operations require authentication: + +```javascript +// Example: Fetch published articles +const response = await fetch('https://example.net/api/v1/article', { + headers: { + 'Authorization': 'Bearer your-token-here' + } +}); +const articles = await response.json(); +``` + +## Core API Documentation + + + + + + +### Content APIs + + + + + + + + + + + +### Internationalization + + + + + +## How to Use This Documentation + +This REST API reference provides two complementary ways to work with the ApostropheCMS API: + +### Written Documentation (This Section) + +The guides on this page and in the navigation are your comprehensive reference for understanding the API: + +- **Learn patterns and concepts** with explanations and context +- **Copy production-ready code** examples into your application +- **Understand field formats** with detailed examples +- **Read offline or on mobile** when you need it + +Start here if you're new to the API or building an integration. + +### API Explorer (Interactive Testing) + +Once you understand the basics, use the API Explorer to test endpoints with your own data: + +- **Test live requests** against your local or deployed ApostropheCMS instance +- **Experiment with parameters** and see real-time responses +- **Validate your authentication** setup before writing code +- **Generate curl commands** for quick testing + +[Open the API Explorer β†’](api-explorer) + +> **Tip**: The written documentation and API Explorer show the same endpoints - use the written docs to learn, then the Explorer to test. + +### OpenAPI Specification + +For advanced workflows, download our complete OpenAPI 3.0 specification: + +- Import into Postman, Insomnia, or other API clients +- Generate client libraries in any language +- Integrate with AI coding assistants +- Build custom tooling and automation + +[Download OpenAPI Spec](/apostrophecms-openapi.yaml){download="apostrophecms-openapi.yaml"} + +## Common Patterns + +### Querying Content + +Retrieve published content with pagination and filtering: + +```javascript +const response = await fetch( + 'https://example.net/api/v1/article?page=1&perPage=10', + { + headers: { 'Authorization': 'Bearer your-token' } + } +); +``` + +### Creating Documents + +Post new content with required fields: + +```javascript +const response = await fetch('https://example.net/api/v1/article', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer your-token' + }, + body: JSON.stringify({ + title: 'My New Article', + slug: 'my-new-article' + }) +}); +``` + +### Working with Locales + +Access content in specific locales using the `aposLocale` query parameter: + +```javascript +const response = await fetch( + 'https://example.net/api/v1/article?aposLocale=fr', + { + headers: { 'Authorization': 'Bearer your-token' } + } +); +``` + +## Need Help? + +- **Stack Overflow**: Tag questions with `apostrophe-cms` +- **Discord**: Join our [community chat](https://chat.apostrophecms.com) +- **GitHub**: Report issues or contribute at [apostrophecms/apostrophe](https://github.com/apostrophecms/apostrophe) + +Ready to start building? Check out the [authentication guide](/reference/api/authentication) to set up your first API request. + diff --git a/package-lock.json b/package-lock.json index 847ea9c0..df6d9468 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "jsdom": "^22.1.0", "marked": "^12.0.2", "socket.io-client": "^4.7.5", + "swagger-ui-dist": "^5.30.3", "uuid": "^10.0.0", "vitepress-plugin-pagefind": "^0.2.4", "vue": "^3.3.4", @@ -1721,6 +1722,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@scarf/scarf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", + "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", + "hasInstallScript": true, + "license": "Apache-2.0" + }, "node_modules/@shikijs/core": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-2.5.0.tgz", @@ -8610,6 +8618,15 @@ "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", "dev": true }, + "node_modules/swagger-ui-dist": { + "version": "5.30.3", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.30.3.tgz", + "integrity": "sha512-giQl7/ToPxCqnUAx2wpnSnDNGZtGzw1LyUw6ZitIpTmdrvpxKFY/94v1hihm0zYNpgp1/VY0jTDk//R0BBgnRQ==", + "license": "Apache-2.0", + "dependencies": { + "@scarf/scarf": "=1.4.0" + } + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", diff --git a/package.json b/package.json index 73145d25..7a6400ac 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "jsdom": "^22.1.0", "marked": "^12.0.2", "socket.io-client": "^4.7.5", + "swagger-ui-dist": "^5.30.3", "uuid": "^10.0.0", "vitepress-plugin-pagefind": "^0.2.4", "vue": "^3.3.4",