openapi: 3.1.0 info: title: Presseportale API version: 1.0.0 description: > REST API for customer integrations after the 2026 migration. Legacy `api_key` query parameters and `X-Api-Key` headers are no longer accepted. servers: - url: /api/v1 security: - sanctumBearer: [] tags: - name: Press Releases - name: Press Release Images - name: Companies - name: Categories - name: Newsletter paths: /press-releases: get: tags: [Press Releases] summary: List own press releases description: Requires `press-releases:read`. parameters: - $ref: '#/components/parameters/StatusFilter' - $ref: '#/components/parameters/PerPage' responses: '200': description: Paginated press release collection. content: application/json: schema: $ref: '#/components/schemas/PaginatedPressReleases' '401': $ref: '#/components/responses/Unauthenticated' '403': $ref: '#/components/responses/Forbidden' '410': $ref: '#/components/responses/LegacyApiKeyGone' post: tags: [Press Releases] summary: Create a press release description: Requires `press-releases:write`. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/StorePressReleaseRequest' responses: '201': description: Press release created. content: application/json: schema: $ref: '#/components/schemas/PressReleaseResponse' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/ValidationError' /press-releases/{pressRelease}: get: tags: [Press Releases] summary: Show one own press release description: Requires `press-releases:read`. parameters: - $ref: '#/components/parameters/PressReleaseId' responses: '200': description: Press release resource. content: application/json: schema: $ref: '#/components/schemas/PressReleaseResponse' '403': $ref: '#/components/responses/Forbidden' patch: tags: [Press Releases] summary: Update one own draft or rejected press release description: Requires `press-releases:write`. parameters: - $ref: '#/components/parameters/PressReleaseId' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdatePressReleaseRequest' responses: '200': description: Press release updated. content: application/json: schema: $ref: '#/components/schemas/PressReleaseResponse' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/ValidationError' delete: tags: [Press Releases] summary: Delete one own unpublished press release description: Requires `press-releases:write`. parameters: - $ref: '#/components/parameters/PressReleaseId' responses: '204': description: Press release deleted. '409': $ref: '#/components/responses/Conflict' /press-releases/{pressRelease}/images: get: tags: [Press Release Images] summary: List images for one own press release description: Requires `press-releases:read`. parameters: - $ref: '#/components/parameters/PressReleaseId' responses: '200': description: Press release image collection. content: application/json: schema: $ref: '#/components/schemas/PressReleaseImageCollection' '403': $ref: '#/components/responses/Forbidden' post: tags: [Press Release Images] summary: Upload an image for one own draft or rejected press release description: Requires `press-release-images:write`. The uploaded image is limited to 5 MB. parameters: - $ref: '#/components/parameters/PressReleaseId' requestBody: required: true content: multipart/form-data: schema: $ref: '#/components/schemas/StorePressReleaseImageRequest' responses: '201': description: Press release image uploaded. content: application/json: schema: $ref: '#/components/schemas/PressReleaseImageResponse' '403': $ref: '#/components/responses/Forbidden' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/ValidationError' /press-release-images/{pressReleaseImage}: delete: tags: [Press Release Images] summary: Delete one own press release image description: Requires `press-release-images:write`; only draft or rejected press releases may be changed. parameters: - $ref: '#/components/parameters/PressReleaseImageId' responses: '204': description: Press release image deleted. '403': $ref: '#/components/responses/Forbidden' '409': $ref: '#/components/responses/Conflict' /companies: get: tags: [Companies] summary: List own companies description: Requires `companies:read`. parameters: - $ref: '#/components/parameters/PerPage' responses: '200': description: Paginated company collection. content: application/json: schema: $ref: '#/components/schemas/PaginatedCompanies' '403': $ref: '#/components/responses/Forbidden' /companies/{company}: get: tags: [Companies] summary: Show one own company description: Requires `companies:read`. parameters: - $ref: '#/components/parameters/CompanyId' responses: '200': description: Company resource. content: application/json: schema: $ref: '#/components/schemas/CompanyResponse' '403': $ref: '#/components/responses/Forbidden' /categories: get: tags: [Categories] summary: List active categories description: Requires `press-releases:read`. responses: '200': description: Category collection. content: application/json: schema: $ref: '#/components/schemas/CategoryCollection' '403': $ref: '#/components/responses/Forbidden' /newsletter/subscribe: post: tags: [Newsletter] summary: Subscribe an email address description: Requires `newsletter:subscribe`. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SubscribeNewsletterRequest' responses: '201': description: Subscription created. content: application/json: schema: $ref: '#/components/schemas/NewsletterSubscriptionResponse' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/ValidationError' components: securitySchemes: sanctumBearer: type: http scheme: bearer bearerFormat: Sanctum personal access token parameters: PressReleaseId: name: pressRelease in: path required: true schema: type: integer PressReleaseImageId: name: pressReleaseImage in: path required: true schema: type: integer CompanyId: name: company in: path required: true schema: type: integer StatusFilter: name: status in: query required: false schema: type: string enum: [draft, review, published, rejected, archived] PerPage: name: per_page in: query required: false schema: type: integer minimum: 1 maximum: 100 default: 25 responses: Unauthenticated: description: Missing or invalid Bearer token. Forbidden: description: Token ability missing or resource does not belong to the authenticated user. Conflict: description: Requested state transition is not allowed. ValidationError: description: Validation failed. content: application/json: schema: $ref: '#/components/schemas/ValidationError' LegacyApiKeyGone: description: Legacy API keys are no longer supported. content: application/json: schema: $ref: '#/components/schemas/LegacyApiKeyGone' schemas: StorePressReleaseRequest: type: object required: [company_id, category_id, language, title, text] properties: company_id: type: integer category_id: type: integer language: type: string minLength: 2 maxLength: 2 example: de title: type: string maxLength: 255 text: type: string backlink_url: type: string format: uri nullable: true keywords: type: string nullable: true maxLength: 255 status: type: string enum: [draft, review] default: draft teaser_begin: type: integer nullable: true minimum: 0 teaser_end: type: integer nullable: true minimum: 0 no_export: type: boolean nullable: true UpdatePressReleaseRequest: allOf: - $ref: '#/components/schemas/StorePressReleaseRequest' required: [] SubscribeNewsletterRequest: type: object required: [portal, email] properties: portal: type: string enum: [presseecho, businessportal24] email: type: string format: email maxLength: 190 salutation_key: type: string nullable: true maxLength: 20 first_name: type: string nullable: true maxLength: 80 last_name: type: string nullable: true maxLength: 80 StorePressReleaseImageRequest: type: object required: [image] properties: image: type: string format: binary description: JPEG, PNG or WebP image, max. 5 MB. title: type: string nullable: true maxLength: 120 description: type: string nullable: true maxLength: 500 copyright: type: string nullable: true maxLength: 255 is_preview: type: boolean nullable: true PressRelease: type: object properties: id: type: integer uuid: type: string format: uuid legacy: $ref: '#/components/schemas/LegacyReference' portal: type: string enum: [presseecho, businessportal24] language: type: string title: type: string slug: type: string text: type: string backlink_url: type: string nullable: true keywords: type: string nullable: true status: type: string enum: [draft, review, published, rejected, archived] hits: type: integer teaser: type: object properties: begin: type: integer nullable: true end: type: integer nullable: true no_export: type: boolean published_at: type: string format: date-time nullable: true company: $ref: '#/components/schemas/Company' category: $ref: '#/components/schemas/Category' images: type: array items: $ref: '#/components/schemas/PressReleaseImage' created_at: type: string format: date-time nullable: true updated_at: type: string format: date-time nullable: true Company: type: object properties: id: type: integer legacy: $ref: '#/components/schemas/LegacyReference' portal: type: string enum: [presseecho, businessportal24] type: type: string nullable: true name: type: string slug: type: string email: type: string nullable: true website: type: string nullable: true phone: type: string nullable: true country_code: type: string nullable: true is_active: type: boolean created_at: type: string format: date-time nullable: true updated_at: type: string format: date-time nullable: true Category: type: object properties: id: type: integer legacy: $ref: '#/components/schemas/LegacyReference' portal: type: string enum: [presseecho, businessportal24] nullable: true is_active: type: boolean translations: type: object additionalProperties: type: object properties: name: type: string slug: type: string description: type: string nullable: true PressReleaseImage: type: object properties: id: type: integer press_release_id: type: integer url: type: string format: uri disk: type: string path: type: string title: type: string nullable: true description: type: string nullable: true copyright: type: string nullable: true is_preview: type: boolean sort_order: type: integer width: type: integer nullable: true height: type: integer nullable: true mime: type: string nullable: true created_at: type: string format: date-time nullable: true updated_at: type: string format: date-time nullable: true LegacyReference: type: object properties: portal: type: string nullable: true id: type: integer nullable: true PressReleaseResponse: type: object properties: data: $ref: '#/components/schemas/PressRelease' PressReleaseImageResponse: type: object properties: data: $ref: '#/components/schemas/PressReleaseImage' CompanyResponse: type: object properties: data: $ref: '#/components/schemas/Company' PaginatedPressReleases: type: object properties: data: type: array items: $ref: '#/components/schemas/PressRelease' links: type: object meta: type: object PaginatedCompanies: type: object properties: data: type: array items: $ref: '#/components/schemas/Company' links: type: object meta: type: object CategoryCollection: type: object properties: data: type: array items: $ref: '#/components/schemas/Category' PressReleaseImageCollection: type: object properties: data: type: array items: $ref: '#/components/schemas/PressReleaseImage' NewsletterSubscriptionResponse: type: object properties: message: type: string data: type: object properties: id: type: integer portal: type: string email: type: string format: email is_confirmed: type: boolean LegacyApiKeyGone: type: object properties: message: type: string example: Legacy API keys are no longer supported. migration_url: type: string format: uri docs_url: type: string format: uri ValidationError: type: object properties: message: type: string errors: type: object additionalProperties: type: array items: type: string