openapi: 3.0.3
info:
title: 'PSI Backend API (2.1.0)'
description: 'This is the PSI Backend API Documentation.'
version: 1.0.0
servers:
- url: 'https://api.psiproductfinder.de'
tags:
- name: Authentication
description: ''
- name: 'Product Controller'
description: ''
- name: 'Image Controller'
description: ''
- name: Endpoints
description: ''
- name: 'Product Group Controller'
description: ''
components:
securitySchemes:
default:
type: http
scheme: bearer
description: ''
security:
-
default: []
paths:
/v2/auth:
post:
summary: Authenticate
operationId: authenticate
description: "This endpoint allows you to authenticate and retrieve an access_token and a refresh_token.\nThe access_token must be included in the header of every API request to access protected resources.\nYou can log in using your standard PSI account credentials. However, to avoid potential issues caused by password changes of regular user accounts,\nwe strongly recommend creating a dedicated Sub-Account for API access. You can set up a Sub-Account in your PSI account settings (https://www.psi-network.de/)."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
access_token: eyJ0eXAidemoV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwcLmRlIiwiYXVkIjoicHNpcHJvZHVjdansmRlci5kZSIsImp0adIeoQzNjMwIiwiaWF0IjoxNzM3MDE5NTQ2LjE2OTkyMiwibmJmIjoxNzM3MDE5NTQ2LjE2OTkyMiwiZXhwIjoxNzM3MDE5NTQ2LjE2OTkyMiwicGF5bG9hZCI6eyJwc2lubyI6NDM2MzAsInVzZXJfaWQiOjEyNDcyOSwiZ3JvdXBzIjoiMTQiLCJlbWFpbCI6ImZyYW5rQHJoZWluc2NoYWZlLmRlIn19
refresh_token: 07070512341eacdemo3a64267c377cdcf06501
expires_in: 1737019546
properties:
access_token:
type: string
example: eyJ0eXAidemoV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwcLmRlIiwiYXVkIjoicHNpcHJvZHVjdansmRlci5kZSIsImp0adIeoQzNjMwIiwiaWF0IjoxNzM3MDE5NTQ2LjE2OTkyMiwibmJmIjoxNzM3MDE5NTQ2LjE2OTkyMiwiZXhwIjoxNzM3MDE5NTQ2LjE2OTkyMiwicGF5bG9hZCI6eyJwc2lubyI6NDM2MzAsInVzZXJfaWQiOjEyNDcyOSwiZ3JvdXBzIjoiMTQiLCJlbWFpbCI6ImZyYW5rQHJoZWluc2NoYWZlLmRlIn19
refresh_token:
type: string
example: 07070512341eacdemo3a64267c377cdcf06501
expires_in:
type: integer
example: 1737019546
400:
description: ''
content:
application/json:
schema:
type: object
example:
errors: 'Username or Password is wrong.'
properties:
errors:
type: string
example: 'Username or Password is wrong.'
tags:
- Authentication
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
username:
type: string
description: 'Your Username - is the same as you login to other PSI Services (Productfinder, Network..), can be an E-Mail Adress or the PSI-Number.'
example: demo@psi-network.de
password:
type: string
description: 'Your Password.'
example: password
required:
- username
- password
security: []
/v2/refresh:
post:
summary: 'Refresh Token'
operationId: refreshToken
description: 'Your access_token is valid for the duration specified in the expires_in field of the authentication response (e.g., typically 1 hour). Once the token expires, you must generate a new one to continue accessing protected resources.'
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
access_token: eyJ0eXAidemoV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwcLmRlIiwiYXVkIjoicHNpcHJvZHVjdansmRlci5kZSIsImp0adIeoQzNjMwIiwiaWF0IjoxNzM3MDE5NTQ2LjE2OTkyMiwibmJmIjoxNzM3MDE5NTQ2LjE2OTkyMiwiZXhwIjoxNzM3MDE5NTQ2LjE2OTkyMiwicGF5bG9hZCI6eyJwc2lubyI6NDM2MzAsInVzZXJfaWQiOjEyNDcyOSwiZ3JvdXBzIjoiMTQiLCJlbWFpbCI6ImZyYW5rQHJoZWluc2NoYWZlLmRlIn19
expires_in: 1737020073
properties:
access_token:
type: string
example: eyJ0eXAidemoV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwcLmRlIiwiYXVkIjoicHNpcHJvZHVjdansmRlci5kZSIsImp0adIeoQzNjMwIiwiaWF0IjoxNzM3MDE5NTQ2LjE2OTkyMiwibmJmIjoxNzM3MDE5NTQ2LjE2OTkyMiwiZXhwIjoxNzM3MDE5NTQ2LjE2OTkyMiwicGF5bG9hZCI6eyJwc2lubyI6NDM2MzAsInVzZXJfaWQiOjEyNDcyOSwiZ3JvdXBzIjoiMTQiLCJlbWFpbCI6ImZyYW5rQHJoZWluc2NoYWZlLmRlIn19
expires_in:
type: integer
example: 1737020073
tags:
- Authentication
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
username:
type: string
description: 'Your E-Mail Adress or the PSI-Number, at the moment you can not use a sub account here.'
example: demo@psi-network.de
refresh_token:
type: string
description: 'Your refresh token.'
example: 07070512341eacdemo3a64267c377cdcf06501
required:
- username
- refresh_token
security: []
/v2/products:
get:
summary: 'Get Entities'
operationId: getEntities
description: 'The Get Entities endpoint allows you to retrieve all products associated with your PSI number. It returns all products that belong to your account, but you can customize the results using optional query parameters.'
parameters:
-
in: query
name: language
description: ''
example: en
required: false
schema:
type: string
description: ''
example: en
enum:
- de
- en
-
in: query
name: locale
description: ''
example: en
required: false
schema:
type: string
description: ''
example: en
enum:
- de
- en
-
in: query
name: filter
description: ''
example: outdated
required: false
schema:
type: string
description: ''
example: outdated
nullable: true
-
in: query
name: search
description: ''
example: Suchen
required: false
schema:
type: string
description: ''
example: Suchen
nullable: true
-
in: query
name: page
description: 'Must be at least 1.'
example: 1.0
required: false
schema:
type: number
description: 'Must be at least 1.'
example: 1.0
-
in: query
name: size
description: 'Must be at least 1. Must not be greater than 100.'
example: 20
required: false
schema:
type: number
description: 'Must be at least 1. Must not be greater than 100.'
example: 20
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
code: 200
status: OK
data: []
meta: {}
properties:
code:
type: integer
example: 200
status:
type: string
example: OK
data:
type: array
example: []
meta:
type: object
properties: {}
400:
description: ''
content:
application/json:
schema:
type: object
example:
code: '404'
status: 'Not found'
message: 'No products found.'
properties:
code:
type: string
example: '404'
status:
type: string
example: 'Not found'
message:
type: string
example: 'No products found.'
tags:
- 'Product Controller'
/v2/products/store:
post:
summary: 'Create Entity'
operationId: createEntity
description: "Create an English product or add a German translation to an existing variant. For a translation, set `language` to `de` and use the existing variant's `product_number`. Language defaults to `en`; `data` returns the full product.\n
`name`, `product_number` and `master_product_number` are required. Group codes are listed in the PSI code spreadsheet."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
code: 200
status: OK
message: 'The product demo-001 has been successfully created.'
data:
product_identifier: p-demo
variant_identifier: v-demo
product_number: demo-001
name: 'Demo Product'
properties:
code:
type: integer
example: 200
status:
type: string
example: OK
message:
type: string
example: 'The product demo-001 has been successfully created.'
data:
type: object
properties:
product_identifier:
type: string
example: p-demo
variant_identifier:
type: string
example: v-demo
product_number:
type: string
example: demo-001
name:
type: string
example: 'Demo Product'
400:
description: ''
content:
application/json:
schema:
type: object
example:
code: 400
status: 'Bad Request'
message: 'Validation failed.'
errors:
name:
- 'The name field is required.'
properties:
code:
type: integer
example: 400
status:
type: string
example: 'Bad Request'
message:
type: string
example: 'Validation failed.'
errors:
type: object
properties:
name:
type: array
example:
- 'The name field is required.'
items:
type: string
tags:
- 'Product Controller'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: 'The variant or translation name.'
example: 'Demo Product'
product_number:
type: string
description: 'Unique variant number.'
example: demo-001
language:
type: enum
description: 'Product language. Defaults to en. Use de for a German translation.'
example: en
enum:
- de
- en
locale:
type: enum
description: 'Response language.'
example: en
enum:
- de
- en
master_product_number:
type: string
description: 'Groups variants under one product.'
example: demo-001
brand:
type: string
description: 'English only. Brand name.'
example: 'PSI Demo'
description:
type: string
description: 'Product description.'
example: 'This is a demo product'
tags:
type: string
description: 'Comma-separated product tags.'
example: 'demo, promotion'
ean_code:
type: string
description: 'English only. EAN code.'
example: '4006381333931'
product_groups:
type: array
description: 'English only. PSI product group codes.'
example:
- '05138008'
- '08094001'
items:
type: string
certificates:
type: array
description: 'English only. PSI certificate codes.'
example:
- CERT-04200000
items:
type: string
colors:
type: array
description: 'English only. PSI color group codes.'
example:
- CG-BLAK5
items:
type: string
color_description:
type: string
description: 'Color description.'
example: Black
country_origin:
type: string
description: 'English only. PSI country code.'
example: CC-DE
made_in:
type: string
description: 'English only. PSI country code.'
example: CC-DE
images:
type: array
description: 'Up to 5 images. Each needs at least one of src, name or description; src is required in English.'
example:
-
src: 'https://psiproductfinder.de/images/logo/logo.svg'
name: 'Demo product image'
description: 'Front view of the product'
items:
type: object
properties:
src:
type: string
description: 'Image URL. Required in English.'
example: 'https://psiproductfinder.de/images/logo/logo.svg'
name:
type: string
description: 'Image name.'
example: 'Demo product image'
description:
type: string
description: 'Image description.'
example: 'Front view of the product'
delivery_time_max:
type: integer
description: 'English only. Maximum delivery time.'
example: 3
delivery_time_min:
type: integer
description: 'English only. Minimum delivery time.'
example: 1
finishings:
type: array
description: 'Up to 4 finishings. Each needs a PSI finishing code; included defaults to false.'
example:
-
group: FG-APPN11
included: false
description: 'Demo application'
items:
type: object
properties:
group:
type: string
description: 'PSI finishing code.'
example: FG-APPN11
included:
type: boolean
description: 'Whether the finishing is included in the price. Defaults to false.'
example: false
description:
type: string
description: 'Finishing description.'
example: 'Demo application'
required:
- group
finishings_information:
type: string
description: 'Finishing information.'
example: 'Screen printing available.'
legal_information:
type: string
description: 'Legal information.'
example: 'Not suitable for children under 3.'
material_description:
type: string
description: 'Material description.'
example: Acrylic
materials:
type: array
description: 'English only. PSI material group codes.'
example:
- MG-ACRC7
items:
type: string
measurement_length:
type: integer
description: 'English only. Product length.'
example: 100
measurement_volume:
type: integer
description: 'English only. Product volume.'
example: 10
measurement_height:
type: integer
description: 'English only. Product height.'
example: 150
measurement_width:
type: integer
description: 'English only. Product width.'
example: 135
measurement_information:
type: string
description: 'Measurement information.'
example: 'Dimensions in millimetres.'
weight_netto:
type: integer
description: 'English only. Net weight.'
example: 10
weight_brutto:
type: integer
description: 'English only. Gross weight.'
example: 13
minimum_order_amount:
type: integer
description: 'English only. Minimum order quantity.'
example: 1
packaging:
type: integer
description: 'English only. Packaging quantity.'
example: 2
price_ranges:
type: array
description: 'English only. Up to 5 ranges; each needs amount and either price_ek or price_uvp.'
example:
-
amount: 1
price_ek: 1.5
price_uvp: 2
items:
type: object
properties:
amount:
type: integer
description: 'Quantity for this price.'
example: 1
price_ek:
type: number
description: 'Purchase price. Required if price_uvp is omitted.'
example: 1.5
price_uvp:
type: number
description: 'Retail price. Required if price_ek is omitted.'
example: 2.0
required:
- amount
price_ranges_information:
type: string
description: 'Price range information.'
example: 'Prices in EUR, excluding VAT.'
product_information:
type: string
description: 'Product information.'
example: 'Reusable acrylic promotional product.'
stock_available:
type: boolean
description: 'English only. Whether the product is always in stock.'
example: true
delivery_information:
type: string
description: 'Delivery information.'
example: 'Ships within 3 business days.'
target_group:
type: string
description: 'Target group.'
example: Adults
video:
type: string
description: 'English only. Video URL.'
example: 'https://example.com/demo-product.mp4'
required:
- name
- product_number
- master_product_number
'/v2/products/{identifier}':
get:
summary: 'Get Entity'
operationId: getEntity
description: 'This endpoint is used to retrieve a specific product or variant. You can identify the entity using one of the following methods: Internal Identifier: A unique identifier generated from your master_product_number, PSI number, and product_number. Identifiers starting with p- refer to a master product, and identifiers starting with v- refer to a variant. Product Number: You can also use your custom product_number as an identifier. Note: If you request a master product (p-), the response will include all associated variants.'
parameters:
-
in: query
name: language
description: ''
example: en
required: false
schema:
type: string
description: ''
example: en
enum:
- de
- en
-
in: query
name: locale
description: ''
example: en
required: false
schema:
type: string
description: ''
example: en
enum:
- de
- en
responses:
400:
description: ''
content:
application/json:
schema:
type: object
example:
code: 400
status: 'Bad request'
properties:
code:
type: integer
example: 400
status:
type: string
example: 'Bad request'
404:
description: ''
content:
application/json:
schema:
type: object
example:
code: 404
status: 'Not found'
message: "No product found with identifier 'v-demo'."
properties:
code:
type: integer
example: 404
status:
type: string
example: 'Not found'
message:
type: string
example: "No product found with identifier 'v-demo'."
500:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Server Error'
properties:
message:
type: string
example: 'Server Error'
tags:
- 'Product Controller'
parameters:
-
in: path
name: identifier
description: 'Optional parameter. required.'
required: true
schema:
type: string
examples:
omitted:
summary: 'When the value is omitted'
value: ''
present:
summary: 'When the value is present'
value: p-c2a1cf5x
'/v2/products/update/{identifier}':
patch:
summary: 'Update Entity'
operationId: updateEntity
description: "Update a product or translation. Omitted fields remain unchanged. Use the variant identifier in the URL; set `language` to `de` to update its German translation. `data` returns the full product.\n
Non-empty relationship arrays replace existing values. An empty `price_ranges` array clears prices; other empty arrays are ignored. Fields marked English only cannot be changed on a translation."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
code: 200
status: OK
message: 'The product demo-001 has been successfully updated.'
data:
product_identifier: p-demo
variant_identifier: v-demo
product_number: demo-001
name: 'Demo Product'
properties:
code:
type: integer
example: 200
status:
type: string
example: OK
message:
type: string
example: 'The product demo-001 has been successfully updated.'
data:
type: object
properties:
product_identifier:
type: string
example: p-demo
variant_identifier:
type: string
example: v-demo
product_number:
type: string
example: demo-001
name:
type: string
example: 'Demo Product'
400:
description: ''
content:
application/json:
schema:
type: object
example:
code: 400
status: 'Bad Request'
message: 'Validation failed.'
errors:
name:
- 'The name field is required.'
properties:
code:
type: integer
example: 400
status:
type: string
example: 'Bad Request'
message:
type: string
example: 'Validation failed.'
errors:
type: object
properties:
name:
type: array
example:
- 'The name field is required.'
items:
type: string
404:
description: ''
content:
application/json:
schema:
type: object
example:
code: '404'
status: 'Not found'
message: "No product found with identifier 'v-88c62663'."
properties:
code:
type: string
example: '404'
status:
type: string
example: 'Not found'
message:
type: string
example: "No product found with identifier 'v-88c62663'."
tags:
- 'Product Controller'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: 'The variant or translation name.'
example: 'Demo Product'
product_number:
type: string
description: 'English only. Unique variant number.'
example: demo-001
language:
type: enum
description: 'Product language. Defaults to en. Use de for a German translation.'
example: en
enum:
- de
- en
locale:
type: enum
description: 'Response language.'
example: en
enum:
- de
- en
master_product_number:
type: string
description: 'Groups variants under one product.'
example: demo-001
brand:
type: string
description: 'English only. Brand name.'
example: 'PSI Demo'
description:
type: string
description: 'Product description.'
example: 'This is a demo product'
tags:
type: string
description: 'Comma-separated product tags.'
example: 'demo, promotion'
ean_code:
type: string
description: 'English only. EAN code.'
example: '4006381333931'
product_groups:
type: array
description: 'English only. PSI product group codes.'
example:
- '05138008'
- '08094001'
items:
type: string
certificates:
type: array
description: 'English only. PSI certificate codes.'
example:
- CERT-04200000
items:
type: string
colors:
type: array
description: 'English only. PSI color group codes.'
example:
- CG-BLAK5
items:
type: string
color_description:
type: string
description: 'Color description.'
example: Black
country_origin:
type: string
description: 'English only. PSI country code.'
example: CC-DE
made_in:
type: string
description: 'English only. PSI country code.'
example: CC-DE
images:
type: array
description: 'Up to 5 images. Each needs at least one of src, name or description; src is required in English.'
example:
-
src: 'https://psiproductfinder.de/images/logo/logo.svg'
name: 'Demo product image'
description: 'Front view of the product'
items:
type: object
properties:
src:
type: string
description: 'Image URL. Required in English.'
example: 'https://psiproductfinder.de/images/logo/logo.svg'
name:
type: string
description: 'Image name.'
example: 'Demo product image'
description:
type: string
description: 'Image description.'
example: 'Front view of the product'
delivery_time_max:
type: integer
description: 'English only. Maximum delivery time.'
example: 3
delivery_time_min:
type: integer
description: 'English only. Minimum delivery time.'
example: 1
finishings:
type: array
description: 'Up to 4 finishings. Each needs a PSI finishing code; included defaults to false.'
example:
-
group: FG-APPN11
included: false
description: 'Demo application'
items:
type: object
properties:
group:
type: string
description: 'PSI finishing code.'
example: FG-APPN11
included:
type: boolean
description: 'Whether the finishing is included in the price. Defaults to false.'
example: false
description:
type: string
description: 'Finishing description.'
example: 'Demo application'
required:
- group
finishings_information:
type: string
description: 'Finishing information.'
example: 'Screen printing available.'
legal_information:
type: string
description: 'Legal information.'
example: 'Not suitable for children under 3.'
material_description:
type: string
description: 'Material description.'
example: Acrylic
materials:
type: array
description: 'English only. PSI material group codes.'
example:
- MG-ACRC7
items:
type: string
measurement_length:
type: integer
description: 'English only. Product length.'
example: 100
measurement_volume:
type: integer
description: 'English only. Product volume.'
example: 10
measurement_height:
type: integer
description: 'English only. Product height.'
example: 150
measurement_width:
type: integer
description: 'English only. Product width.'
example: 135
measurement_information:
type: string
description: 'Measurement information.'
example: 'Dimensions in millimetres.'
weight_netto:
type: integer
description: 'English only. Net weight.'
example: 10
weight_brutto:
type: integer
description: 'English only. Gross weight.'
example: 13
minimum_order_amount:
type: integer
description: 'English only. Minimum order quantity.'
example: 1
packaging:
type: integer
description: 'English only. Packaging quantity.'
example: 2
price_ranges:
type: array
description: 'English only. Up to 5 ranges; each needs amount and either price_ek or price_uvp.'
example:
-
amount: 1
price_ek: 1.5
price_uvp: 2
items:
type: object
properties:
amount:
type: integer
description: 'Quantity for this price.'
example: 1
price_ek:
type: number
description: 'Purchase price. Required if price_uvp is omitted.'
example: 1.5
price_uvp:
type: number
description: 'Retail price. Required if price_ek is omitted.'
example: 2.0
required:
- amount
price_ranges_information:
type: string
description: 'Price range information.'
example: 'Prices in EUR, excluding VAT.'
product_information:
type: string
description: 'Product information.'
example: 'Reusable acrylic promotional product.'
stock_available:
type: boolean
description: 'English only. Whether the product is always in stock.'
example: true
delivery_information:
type: string
description: 'Delivery information.'
example: 'Ships within 3 business days.'
target_group:
type: string
description: 'Target group.'
example: Adults
video:
type: string
description: 'English only. Video URL.'
example: 'https://example.com/demo-product.mp4'
parameters:
-
in: path
name: identifier
description: 'Optional parameter. Variant identifier.'
required: true
schema:
type: string
examples:
omitted:
summary: 'When the value is omitted'
value: ''
present:
summary: 'When the value is present'
value: v-88c62663
'/v2/products/delete/{identifier}':
delete:
summary: 'Delete Entity'
operationId: deleteEntity
description: 'To delete a variant, translation, or product, you need to provide the identifier (e.g., p-88c62663 for a product or v-88c62663 for a variant). If you want to delete a translation in a language other than the default (English), you must also specify the language parameter.'
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
code: 200
status: success
message: "Product with identifier ':identifier' has been successfully deleted."
properties:
code:
type: integer
example: 200
status:
type: string
example: success
message:
type: string
example: "Product with identifier ':identifier' has been successfully deleted."
404:
description: ''
content:
application/json:
schema:
type: object
example:
code: '404'
status: 'Not found'
message: "No translation found for the product with identifier 'v-88c62663' in locale 'en'."
properties:
code:
type: string
example: '404'
status:
type: string
example: 'Not found'
message:
type: string
example: "No translation found for the product with identifier 'v-88c62663' in locale 'en'."
tags:
- 'Product Controller'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
language:
type: enum
description: 'Must be one of: