diff --git a/openapi.yaml b/openapi.yaml new file mode 100644 index 0000000..c7508b5 --- /dev/null +++ b/openapi.yaml @@ -0,0 +1,668 @@ +openapi: 3.0.3 + +info: + title: MokoSuiteOpenGraph API + version: 1.0.0 + description: | + REST API for managing Open Graph, SEO meta, and structured-data tags in + Joomla via the MokoSuiteOpenGraph extension. + + The API follows Joomla's Web Services conventions and returns responses in + [JSON:API](https://jsonapi.org/) format. All endpoints require + authentication via a Joomla API token. + contact: + name: Moko Consulting + email: hello@mokoconsulting.tech + license: + name: GPL-3.0-or-later + url: https://www.gnu.org/licenses/gpl-3.0.html + +servers: + - url: /api/index.php/v1 + description: Joomla Web Services API + +security: + - apiToken: [] + +tags: + - name: Tags + description: CRUD operations for Open Graph tag records + +paths: + /mokoog/tags: + get: + operationId: listTags + summary: List OG tags + description: | + Returns a paginated collection of OG tag records. Supports filtering + by content type, published state, and language. + tags: [Tags] + parameters: + - name: "filter[content_type]" + in: query + description: Filter by content type (e.g. `com_content`, `menu`, `com_mokoshop`) + schema: + type: string + example: com_content + - name: "filter[content_id]" + in: query + description: Filter by content ID + schema: + type: integer + example: 42 + - name: "filter[published]" + in: query + description: Filter by published state + schema: + type: integer + enum: [0, 1] + - name: "filter[language]" + in: query + description: Filter by language tag (e.g. `en-GB`, `*`) + schema: + type: string + example: "*" + - name: "filter[search]" + in: query + description: Free-text search across tag fields + schema: + type: string + - name: "page[offset]" + in: query + description: Number of records to skip (pagination offset) + schema: + type: integer + minimum: 0 + default: 0 + - name: "page[limit]" + in: query + description: Maximum number of records to return + schema: + type: integer + minimum: 1 + maximum: 100 + default: 25 + - name: "list[fullordering]" + in: query + description: Sort order for results + schema: + type: string + enum: + - a.id ASC + - a.id DESC + - a.og_title ASC + - a.og_title DESC + - a.modified ASC + - a.modified DESC + default: a.modified DESC + responses: + "200": + description: A JSON:API collection of OG tags + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/TagCollection" + example: + links: + self: "/api/index.php/v1/mokoog/tags" + data: + - type: tags + id: "1" + attributes: + content_type: com_content + content_id: 42 + og_title: "My Article Title" + og_description: "A brief description for social sharing." + og_image: "images/mokoog/og-banner.jpg" + og_type: article + seo_title: "My Article | Example Site" + meta_description: "A brief meta description for search engines." + robots: "index, follow" + canonical_url: "https://example.com/my-article" + language: "*" + published: 1 + created: "2026-06-01T12:00:00+00:00" + modified: "2026-06-15T08:30:00+00:00" + meta: + total-pages: 1 + "401": + $ref: "#/components/responses/Unauthorized" + + post: + operationId: createTag + summary: Create an OG tag + description: | + Creates a new OG tag record. The combination of `content_type`, + `content_id`, and `language` must be unique. + tags: [Tags] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/TagCreateRequest" + example: + content_type: com_content + content_id: 42 + og_title: "My Article Title" + og_description: "A brief description for social sharing." + og_image: "images/mokoog/og-banner.jpg" + og_type: article + language: "*" + published: 1 + responses: + "200": + description: The created tag + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/TagDocument" + example: + links: + self: "/api/index.php/v1/mokoog/tags/1" + data: + type: tags + id: "1" + attributes: + content_type: com_content + content_id: 42 + og_title: "My Article Title" + og_description: "A brief description for social sharing." + og_image: "images/mokoog/og-banner.jpg" + og_type: article + seo_title: "" + meta_description: "" + robots: "" + canonical_url: "" + language: "*" + published: 1 + created: "2026-06-23T10:00:00+00:00" + modified: "2026-06-23T10:00:00+00:00" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + + /mokoog/tags/{id}: + parameters: + - $ref: "#/components/parameters/TagId" + + get: + operationId: getTag + summary: Get a single OG tag + tags: [Tags] + responses: + "200": + description: A single OG tag resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/TagDocument" + example: + links: + self: "/api/index.php/v1/mokoog/tags/1" + data: + type: tags + id: "1" + attributes: + content_type: com_content + content_id: 42 + og_title: "My Article Title" + og_description: "A brief description for social sharing." + og_image: "images/mokoog/og-banner.jpg" + og_type: article + seo_title: "My Article | Example Site" + meta_description: "A brief meta description for search engines." + robots: "index, follow" + canonical_url: "https://example.com/my-article" + language: "*" + published: 1 + created: "2026-06-01T12:00:00+00:00" + modified: "2026-06-15T08:30:00+00:00" + "401": + $ref: "#/components/responses/Unauthorized" + "404": + $ref: "#/components/responses/NotFound" + + patch: + operationId: updateTag + summary: Update an OG tag + description: Partially updates an existing OG tag. Only supplied fields are changed. + tags: [Tags] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/TagUpdateRequest" + example: + og_title: "Updated Title" + og_description: "Updated social description." + published: 0 + responses: + "200": + description: The updated tag + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/TagDocument" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "404": + $ref: "#/components/responses/NotFound" + + delete: + operationId: deleteTag + summary: Delete an OG tag + tags: [Tags] + responses: + "204": + description: Tag deleted successfully + "401": + $ref: "#/components/responses/Unauthorized" + "404": + $ref: "#/components/responses/NotFound" + + /mokoog/lookup/{content_type}/{content_id}: + get: + operationId: lookupTag + summary: Look up an OG tag by content type and content ID + description: | + Resolves an OG tag by its `content_type` and `content_id` pair and + returns the full tag resource. This is a convenience endpoint that + avoids the caller needing to know the internal tag ID. + tags: [Tags] + parameters: + - name: content_type + in: path + required: true + description: | + The content type identifier (e.g. `com_content`, `menu`, + `com_mokoshop`). Must match the pattern `[a-z][a-z0-9_.]*`. + schema: + type: string + pattern: "^[a-z][a-z0-9_.]*$" + example: com_content + - name: content_id + in: path + required: true + description: The content item ID + schema: + type: integer + minimum: 1 + example: 42 + responses: + "200": + description: The matching OG tag resource + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/TagDocument" + "400": + description: Missing or invalid content_type / content_id + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/ErrorResponse" + example: + errors: + - title: Bad Request + status: 400 + detail: "content_type and content_id are required" + "401": + $ref: "#/components/responses/Unauthorized" + "404": + description: No OG tag found for the given content_type and content_id + content: + application/vnd.api+json: + schema: + $ref: "#/components/schemas/ErrorResponse" + example: + errors: + - title: Not Found + status: 404 + detail: "OG tag not found for com_content:42" + +components: + securitySchemes: + apiToken: + type: apiKey + name: X-Joomla-Token + in: header + description: | + Joomla API token. Can also be passed as the `api-token` query + parameter. Generate a token from the Joomla administrator panel + under Users > Manage > [user] > Joomla API Token tab. + + parameters: + TagId: + name: id + in: path + required: true + description: The OG tag record ID + schema: + type: integer + minimum: 1 + example: 1 + + schemas: + TagAttributes: + type: object + description: Full set of OG tag attributes returned by the API + properties: + content_type: + type: string + description: | + Content type identifier (e.g. `com_content`, `menu`, + `com_mokoshop`). Must match `[a-z][a-z0-9_.]*`. + pattern: "^[a-z][a-z0-9_.]*$" + maxLength: 100 + example: com_content + content_id: + type: integer + description: The ID of the associated content item + minimum: 1 + example: 42 + og_title: + type: string + description: Open Graph title (`og:title`) + maxLength: 255 + example: "My Article Title" + og_description: + type: string + description: Open Graph description (`og:description`) + example: "A brief description for social sharing." + og_image: + type: string + description: Relative path to the Open Graph image (`og:image`) + maxLength: 512 + example: "images/mokoog/og-banner.jpg" + og_type: + type: string + description: Open Graph type (`og:type`) + default: article + enum: + - article + - website + - product + - profile + - book + - music.song + - music.album + - video.movie + - video.episode + - video.other + example: article + seo_title: + type: string + description: SEO page title (used in `