From d9f26928c04a6522b10079f4a6e4d21efc63be9b Mon Sep 17 00:00:00 2001 From: Miradil Zeynalli Date: Wed, 23 Sep 2026 00:40:17 +0200 Subject: [PATCH] Added copiable minimal examples for integrations --- CLAUDE.md | 3 +- docs/az/docs/integrations/azericard/index.md | 46 +- .../integrations/azericard/official/api.md | 2077 +++++ docs/az/docs/integrations/epoint/index.md | 28 + .../az/docs/integrations/kapitalbank/index.md | 27 + .../integrations/kapitalbank/official/api.md | 1046 +++ docs/az/docs/integrations/lsim/index.md | 30 +- .../az/docs/integrations/lsim/official/api.md | 414 + .../integrations/posta-guvercini/index.md | 22 + .../posta-guvercini/official/api.md | 341 + docs/az/mkdocs.yml | 4 + docs/az/partial.yml | 54 - docs/en/docs/integrations/clopos/index.md | 27 +- .../docs/integrations/clopos/official/api.md | 6842 +++++++++++++++++ docs/en/mkdocs.yml | 1 + docs/en/partial.yml | 9 - packages/lsim/README.md | 2 +- packages/lsim/src/integrify/lsim/__init__.py | 2 +- 18 files changed, 10890 insertions(+), 85 deletions(-) create mode 100644 docs/az/docs/integrations/azericard/official/api.md create mode 100644 docs/az/docs/integrations/kapitalbank/official/api.md create mode 100644 docs/az/docs/integrations/lsim/official/api.md create mode 100644 docs/az/docs/integrations/posta-guvercini/official/api.md delete mode 100644 docs/az/partial.yml create mode 100644 docs/en/docs/integrations/clopos/official/api.md delete mode 100644 docs/en/partial.yml diff --git a/CLAUDE.md b/CLAUDE.md index 3a31ae5..5fea647 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -48,11 +48,10 @@ docs/az/docs/integrations// └── api-reference/ # mkdocstrings stubs: client.md, request.md, response.md, enums.md ``` -Then wire it up in three places: +Then wire it up in two places: 1. `pyproject.toml` — `[project.optional-dependencies]` extra, the `all` list, and `[tool.uv.sources]`. 2. `docs/az/mkdocs.yml` — the mkdocstrings `paths` list **and** the `nav` tree. -3. `docs/az/partial.yml` — the matching nav fragment. (English pages, where they exist, mirror this under `docs/en/`.) diff --git a/docs/az/docs/integrations/azericard/index.md b/docs/az/docs/integrations/azericard/index.md index a505495..7f09e3e 100644 --- a/docs/az/docs/integrations/azericard/index.md +++ b/docs/az/docs/integrations/azericard/index.md @@ -12,6 +12,35 @@ [İngliscə](https://developer.azericard.com/en) +Markdown versiyası (bu saytda): [Azericard E-Commerce API](./official/api.md) + +## Sürətli başlanğıc { #quickstart } + +Azericard-da sorğunu brauzer göndərir: kitabxana form datasını hazırlayır, siz isə HTML formu front-a qaytarırsınız: + +```python +from integrify.azericard import AzeriCardClient +from integrify.azericard.helpers import json_to_html_form +from integrify.azericard.schemas.enums import AuthorizationType + +# 1. Form datasını hazırlayın (Azericard-a sorğunu brauzer göndərir) +req = AzeriCardClient.authorization( + amount=10, + currency='AZN', + order='12345678', + desc='Sifariş #1', + trtype=AuthorizationType.DIRECT, +) + +# 2. HTML formu front-a qaytarın: submit olunduqda müştəri ödəniş səhifəsinə keçir +html_form = json_to_html_form(req, with_submit=True) +print(html_form) + +# 3. Nəticə AZERICARD_CALLBACK_URL-ə POST sorğusu kimi gəlir (bax: "Callback Sorğusu") +``` + +Asinxron istifadə üçün `AzeriCardAsyncClient` import edib, eyni metodları `await` ilə çağırın. + ## Sorğular listi { #list-of-requests } | Sorğu metodu | Məqsəd | Azericard API | @@ -29,22 +58,7 @@ Nəzərə alsaq ki, Azericard form submission qəbul edərək, sizə redirectsiz səhifəni açır, form-u backend-dən submit etmık mümkün deyil, məhz front tərəfdən olmalıdır. Ona görə, başqa inteqrasiyalardan fərqli olaraq, Azericard-da kitabxana sorğu atmır, form-da göndərilməli olan data-nı qaytarır. Format JSON olsa da, köməkçi funksiyadan istifadə edərək, HTML formu alın, front-a response kimi göndərə bilərsiniz: -```python -from integrify.azericard.client import AzericardClient -from integrify.azericard.helpers import json_to_html_form - -req = AzericardClient.pay( - amount=1, - currency='AZN', - order='12345678', - desc='test', - country='AZ', -) - -form = json_to_html_form(req) -print(form) #
-# ... -``` +Nümunə üçün yuxarıdakı [Sürətli başlanğıc](#quickstart) bölməsinə baxın. ## Callback Sorğusu { #callback-request } diff --git a/docs/az/docs/integrations/azericard/official/api.md b/docs/az/docs/integrations/azericard/official/api.md new file mode 100644 index 0000000..dccc9e8 --- /dev/null +++ b/docs/az/docs/integrations/azericard/official/api.md @@ -0,0 +1,2077 @@ +# Azericard E-Commerce API + +???+ info + Bu səhifə Azericard-ın rəsmi developer sənədinin ([developer.azericard.com/en](https://developer.azericard.com/en), ingiliscə) Markdown versiyasıdır. Uyğunsuzluq olarsa, orijinal mənbə əsas götürülür. + +## 1 Overview + +This manual is intended for use by developers responsible for the merchant payment gateway interface. It describes the interface that merchant systems use to process credit card based e-commerce transactions using the standard CGI/WWW forms posting method. This interface transparently supports various cardholder authentication protocols such as 3D-Secure and Secure Code as well as legacy unauthenticated SSL commerce transactions. + +### 1.1 Transaction flow scenario + +Below diagram describes payment process between client (card holder), merchant and processing center (Azericard) + +![](https://developer.azericard.com/paymentFlow.svg) + +Gateway validates the incoming message and requests a reversal of the pending or completed transaction from the Way4 card system. + +## 2 E-Commerce integration { #integration } + +To make payment merchant first of all should fill the below listed parameters and send data to: +TRTYPE=1 should be sent in the POST request for authorization TRTYPE=0 should be sent in the first POST request for preauthorization, and TRTYPE=21 should be sent to confirm the order after successful return information. + +https://testmpi.3dsecure.az/cgi-bin/cgi\_link + +| Fields | Size | Description | +| --- | --- | --- | +| AMOUNT | 1-12 | Order total amount in float format with decimal point separator | +| CURRENCY | 03 | Order currency: Consist of 3 symbols | +| ORDER | 6-32 | Merchant order ID, numeric. Last 6 digits used as a system trace audit number, which must be unique within a day for the terminal id | +| DESC | 1-50 | Order description | +| MERCH\_NAME | 1-50 | Merchant name (recognizable by cardholder) | +| MERCH\_URL | 1-250 | Merchant primary web site URL | +| TERMINAL | 8 | Merchant Terminal ID assigned by bank | +| EMAIL | 80 | E-mail address for notification. If this field is present Gateway may send transaction results notification to specified e-mail address. | +| TRTYPE | 1 | Transaction type = 0 (Pre-Authorization),Transaction type = 1 (Authorization) | +| COUNTRY | 02 | Merchant shop 2-character country code. Must be provided if merchant system is located in a country other than the gateway server\`s country. | +| MERCH\_GMT | 1-5 | Merchant UTC/GMT time zone offset (e.g. –3). Must be provided if merchant system is located in a time zone other than the gateway server\`s time zone. | +| BACKREF | 1-250 | Merchant URL for posting authorization result. | +| TIMESTAMP | 14 | Merchant transaction timestamp in GMT: YYYYMMDDHHMMSS. Timestamp difference between merchant server and e-Gateway server must not exceed 1 hour, otherwise e-Gateway will reject this transaction. | +| NONCE | 1-64 | Merchant nonce. Must be filled with 8-32 unpredictable random bytes in hexadecimal format. Must be present if MAC is used. | +| LANG | 2 | Language type | +| P\_SIGN | 1-256 | Merchant MAC in hexadecimal form. | +| NAME | 2-45 | Customer's name (as indicated on the card) | +| M\_INFO | 35000 | Must be a Base64-encoded string of JSON-formatted "parameter": "value data". | + +Below is an example of data prepared for the M\_INFO field: + +"M\_INFO"="ewoiYnJvd3NlclNjcmVlbkhlaWdodCI6IjE5MjAiLAoiYnJvd3NlclNjcmVlbldpZHRoIjoiMTA4MCIsCiJicm93c2VyVFoiOiIwIiwKIm1vYmlsZVBob25lIiA6eyAiY2MiOiI5OTQiLCAic3Vic2NyaWJlciI6IjU1Nzc3Nzc3Nzc3IiB9Cn0=", + +Decoded format: {"browserScreenHeight":"1920","browserScreenWidth":"1080","browserTZ":"0","mobilePhone":{"cc":"994","subscriber":"5077777777"}} + +M\_INFO Parameters description: + +browserScreenHeight - Total height of the Cardholder’s screen in pixels. + +browserScreenWidth - Total width of the Cardholder’s screen in pixels.in pixels. + +browserTZ - Time difference between UTC time and the Cardholder browser local time, in minutes. + +mobilePhone - The mobile phone number provided by the Cardholder. + +Request body should be like below: + +"AMOUNT"="xx", "CURRENCY"="AZN", "ORDER"="xxxxxxxxxxxx", "DESC"="xxxxxxxxxxx xxxx", "MERCH\_NAME"="xxxxx.xxx", "MERCH\_URL"="https://xxxxxxxxxx.xx/xxxx", "MERCH\_GMT"="+4", "TERMINAL"="xxxxxxxxx", "EMAIL"="xxxxx@xxxxx.xx", "TRTYPE"="x", "COUNTRY"="AZ", "TIMESTAMP"="xxxxxxxxxxxxxx", "NONCE"="xxxxxxxxxxxxxxx", "BACKREF"="https://xxxxxxxxxxx/xxxxxxxxxxx/xxxxxx", "LANG=xx", "NAME"="xxxxxx", "M\_INFO"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "P\_SIGN"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +### Response format + +| Fields | Size | Description | +| --- | --- | --- | +| TERMINAL | 8 | Echo from the request | +| TRTYPE | 2 | Echo from the request | +| ORDER | 6-32 | Echo from the request | +| AMOUNT | 12 | Amount authorized. Usually, will be equal to original amount plus acquirer’s fee. | +| CURRENCY | 3 | Echo from the request | +| ACTION | 1 | EGateway action code | +| | | §0 – Transaction successfully completed | +| | | §1 – Duplicate transaction detected | +| | | §2 – Transaction declined  | +| | | §3 – Transaction processing error | +| | | §6 – Repeat of a declined transaction | +| | | §7 - Repeat of a transaction with an authentication error | +| | | §8 - Repeat of a transaction that terminated without a response | +| RC | 02 | Transaction response code (ISO-8583 Field 39) | +| APPROVAL | 06 | Client bank’s approval code (ISO-8583 Field 38). Can be empty if not provided by card management system. | +| RRN | 12 | Merchant bank’s retrieval reference number (ISO-8583 Field 37) | +| INT\_REF | 1-128 | E-Commerce gateway internal reference number | +| TIMESTAMP | 14 | E-Commerce gateway timestamp in GMT: YYYYMMDDHHMMSS | +| NONCE | 1-64 | E-Commerce gateway nonce value. Will be filled with 8-32 unpredictable random bytes in hexadecimal format. Will be present if MAC is used. | +| P\_SIGN | 1-256 | E-Commerce gateway MAC (Message Authentication Code) in hexadecimal form. Will be present if MAC is used. | + +### 2.1 Payment confirmation and refund + +Following the rules of P\_Sign generation should check callback P\_Sign with MPI public key. İf the payment is successful, to complete and refund the payment should send below fields depending on trtype (trtype = 21 – checkout, trtype = 22 – online reversal, trtype = 24 – offline reversal). [Link](#callbackCalc) + +https://testmpi.3dsecure.az/cgi-bin/cgi\_link + +#### 2.1.1 TRTYPE = 21 + +**Note:**The following data must be posted to confirm the payment. The sequence of calculating the P\_SIGN value of the request is indicated in the link.[Link](#trtype21) + +| Fields | Size | Order description | +| --- | --- | --- | +| AMOUNT | 1-12 | Order total amount in float format with decimal point separator | +| CURRENCY | 03 | Order currency: Consist of 3 symbols | +| ORDER | 6-32 | Merchant order ID, numeric. Last 6 digits used as a system trace audit number, which must be unique within a day for the terminal id | +| RRN | 1 | Retrieval reference number from authorization response. | +| INT\_REF | 1-32 | Internal reference number from authorization response. | +| TERMINAL | 8 | Merchant Terminal ID assigned by bank | +| TRTYPE | 2 | Transaction type = 21 (Sales completion) | +| TIMESTAMP | 14 | Merchant transaction timestamp in GMT: YYYYMMDDHHMMSS. Timestamp difference between merchant server and e-Gateway server must not exceed 1 hour, otherwise e-Gateway will reject this transaction. | +| NONCE | 16 | Merchant nonce. Must be filled with 8-32 unpredictable random bytes in hexadecimal format. Must be present if MAC is used. | +| P\_SIGN | 1-256 | Merchant MAC in hexadecimal form. | + +Request body should be like below: + +"AMOUNT"="xx", "CURRENCY"="AZN", "ORDER"="xxxxxxxxxxxx", "RRN"="xxxxxxxxx", "INT\_REF"="xxxxxxxxx", "TERMINAL"="xxxxxxxxx", "TRTYPE"="x", "TIMESTAMP"="xxxxxxxxxxxxxx", "NONCE"="xxxxxxxxxxxxxxx", "LANG=xx", "P\_SIGN"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +#### 2.1.2 TRTYPE = 22 + +**Note:**The following data must be posted for a refund. The sequence of calculation of the P\_SIGN value of the request is mentioned in the link.[Link](#trtype22) + +| Fields | Size | Order description | +| --- | --- | --- | +| AMOUNT | 1-12 | Order total amount in float format with decimal point separator | +| CURRENCY | 03 | Order currency: Consist of 3 symbols | +| ORDER | 6-32 | Merchant order ID, numeric. Last 6 digits used as a system trace audit number, which must be unique within a day for the terminal id | +| RRN | 1 | Retrieval reference number from authorization response. | +| INT\_REF | 1-32 | Internal reference number from authorization response. | +| TERMINAL | 8 | Merchant Terminal ID assigned by bank | +| TRTYPE | 2 | Transaction type = 22 (Online reversal) | +| TIMESTAMP | 14 | Merchant transaction timestamp in GMT: YYYYMMDDHHMMSS. Timestamp difference between merchant server and e-Gateway server must not exceed 1 hour, otherwise e-Gateway will reject this transaction. | +| NONCE | 16 | Merchant nonce. Must be filled with 8-32 unpredictable random bytes in hexadecimal format. Must be present if MAC is used. | +| P\_SIGN | 1-256 | Merchant MAC in hexadecimal form. | + +Request body should be like below: + +"AMOUNT"="xx", "CURRENCY"="AZN", "ORDER"="xxxxxxxxxxxx", "RRN"="xxxxxxxxx", "INT\_REF"="xxxxxxxxx", "TERMINAL"="xxxxxxxxx", "TRTYPE"="x", "TIMESTAMP"="xxxxxxxxxxxxxx", "NONCE"="xxxxxxxxxxxxxxx", "LANG=xx", "P\_SIGN"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +#### 2.1.3 TRTYPE = 24 + +**Note:**The following data must be posted for a refund. The sequence of calculation of the P\_SIGN value of the request is mentioned in the link.[Link](#trtype24) + +| Fields | Size | Order description | +| --- | --- | --- | +| AMOUNT | 1-12 | Order total amount in float format with decimal point separator | +| CURRENCY | 03 | Order currency: Consist of 3 symbols | +| ORDER | 6-32 | Merchant order ID, numeric. Last 6 digits used as a system trace audit number, which must be unique within a day for the terminal id | +| RRN | 1 | Retrieval reference number from authorization response. | +| INT\_REF | 1-32 | Internal reference number from authorization response. | +| TERMINAL | 8 | Merchant Terminal ID assigned by bank | +| TRTYPE | 2 | Transaction type = 24 (Offline reversal) | +| TIMESTAMP | 14 | Merchant transaction timestamp in GMT: YYYYMMDDHHMMSS. Timestamp difference between merchant server and e-Gateway server must not exceed 1 hour, otherwise e-Gateway will reject this transaction. | +| NONCE | 16 | Merchant nonce. Must be filled with 8-32 unpredictable random bytes in hexadecimal format. Must be present if MAC is used. | +| P\_SIGN | 1-256 | Merchant MAC in hexadecimal form. | + +Request body should be like below: + +"AMOUNT"="xx", "CURRENCY"="AZN", "ORDER"="xxxxxxxxxxxx", "RRN"="xxxxxxxxx", "INT\_REF"="xxxxxxxxx", "TERMINAL"="xxxxxxxxx", "TRTYPE"="x", "TIMESTAMP"="xxxxxxxxxxxxxx", "NONCE"="xxxxxxxxxxxxxxx", "LANG=xx", "P\_SIGN"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +### 2.2 P-Sign generation + +MAC is calculated over all fields generated by the merchant system as defined in corresponding format tables (visible and hidden fields generated by the merchant system) except the MAC field (“P\_SIGN”) itself. + +In order to generate or verify the message authentication field, the merchant system must assemble a MAC source string; all field values from the format tables are prefixed with the decimal field length in ASCII and concatenated in a specified order. + +The MAC source string for example is: + +81720078010511.48142003010515302116IT Books. Qty: 2 + +After the MAC source string is assembled, the merchant system must apply a cryptographic algorithm to generate the message authentication code. + +The merchant system must implement SHA256 sign, add MAC source to sign and crypts with private key in hexadecimal format. + +Merchant system implemented by special algorithm fully responsible for the secure storage and usage of corresponding cryptographic keys. An effective key length must be at least 2048 bits for RSA algorithm. + +The order of fields in test terminal (terminal id: The terminal will be presented during the test) is as follows: + +#### 2.2.1 TRTYPE = 0, TRTYPE = 1 + +| Fields | Size | Description | +| --- | --- | --- | +| AMOUNT | 1-12 | Order total amount in float format with decimal point separator | +| CURRENCY | 03 | Order currency: Consist of 3 symbols | +| TERMINAL | 8 | Merchant Terminal ID assigned by bank | +| TRTYPE | 1 | Transaction type = 1 (Finance document) | +| TIMESTAMP | 14 | Merchant transaction timestamp in GMT: YYYYMMDDHHMMSS. Timestamp difference between merchant server and e-Gateway server must not exceed 1 hour, otherwise e-Gateway will reject this transaction. | +| NONCE | 1-64 | Merchant nonce. Must be filled with 8-32 unpredictable random bytes in hexadecimal format. Must be present if MAC is used. | +| MERCH\_URL | 1-250 | Merchant primary web site URL | + +#### 2.2.2 TRTYPE = 21 { #trtype21 } + +| Fields | Size | Description | +| --- | --- | --- | +| AMOUNT | 1-12 | Order total amount in float format with decimal point separator | +| CURRENCY | 03 | Order currency: Consist of 3 symbols | +| TERMINAL | 8 | Merchant Terminal ID assigned by bank | +| TRTYPE | 2 | Transaction type = 21 (Sales completion) | +| ORDER | 6-32 | Merchant order ID, numeric. Last 6 digits used as a system trace audit number, which must be unique within a day for the terminal id | +| RRN | 1 | Retrieval reference number from authorization response. | +| INT\_REF | 1-32 | Internal reference number from authorization response. | + +#### 2.2.3 TRTYPE = 22 { #trtype22 } + +| Fields | Size | Description | +| --- | --- | --- | +| AMOUNT | 1-12 | Order total amount in float format with decimal point separator | +| CURRENCY | 03 | Order currency: Consist of 3 symbols | +| TERMINAL | 8 | Merchant Terminal ID assigned by bank | +| TRTYPE | 2 | Transaction type = 22 (Online reversal) | +| ORDER | 6-32 | Merchant order ID, numeric. Last 6 digits used as a system trace audit number, which must be unique within a day for the terminal id | +| RRN | 1 | Retrieval reference number from authorization response. | +| INT\_REF | 1-32 | Internal reference number from authorization response. | + +#### 2.2.4 TRTYPE = 24 { #trtype24 } + +| Fields | Size | Description | +| --- | --- | --- | +| AMOUNT | 1-12 | Order total amount in float format with decimal point separator | +| CURRENCY | 03 | Order currency: Consist of 3 symbols | +| TERMINAL | 8 | Merchant Terminal ID assigned by bank | +| TRTYPE | 2 | Transaction type = 24 (Offline reversal) | +| ORDER | 6-32 | Merchant order ID, numeric. Last 6 digits used as a system trace audit number, which must be unique within a day for the terminal id | +| RRN | 1 | Retrieval reference number from authorization response. | +| INT\_REF | 1-32 | Internal reference number from authorization response. | + +### 2.3 S2S integration + +**Note:** The indicated type of integration is valid only for merchants with a valid PCI DSS certificate. +TRTYPE=1 should be sent in the POST request for authorization TRTYPE=0 should be sent in the first POST request for preauthorization, and TRTYPE=21 should be sent to confirm the order after successful return information. + +HTTP POST request should be sent to Azericard e-commerce gateway at URL: + +https://testmpi.3dsecure.az/cgi-bin/cgi\_link + +#### Request format + +| Fields | Size | Description | +| --- | --- | --- | +| AMOUNT | 1-12 | Order total amount in float format with decimal point separator | +| CURRENCY | 03 | Order currency: Consist of 3 symbols | +| ORDER | 6-32 | Merchant order ID, numeric. Last 6 digits used as a system trace audit number, which must be unique within a day for the terminal id | +| DESC | 1-50 | Order description | +| MERCH\_NAME | 1-50 | Merchant name (recognizable by cardholder) | +| MERCH\_URL | 1-250 | Merchant primary web site URL | +| TERMINAL | 8 | Merchant Terminal ID assigned by bank | +| EMAIL | 80 | E-mail address for notification. If this field is present Gateway may send transaction results notification to specified e-mail address. | +| TRTYPE | 1 | Transaction type = 0 (Pre-Authorization),Transaction type = 1 (Authorization) | +| COUNTRY | 02 | Merchant shop 2-character country code. Must be provided if merchant system is located in a country other than the gateway server\`s country. | +| MERCH\_GMT | 1-5 | Merchant UTC/GMT time zone offset (e.g. –3). Must be provided if merchant system is located in a time zone other than the gateway server\`s time zone. | +| BACKREF | 1-250 | Merchant URL for posting authorization result. | +| TIMESTAMP | 14 | Merchant transaction timestamp in GMT: YYYYMMDDHHMMSS. Timestamp difference between merchant server and e-Gateway server must not exceed 1 hour, otherwise e-Gateway will reject this transaction. | +| NONCE | 1-64 | Merchant nonce. Must be filled with 8-32 unpredictable random bytes in hexadecimal format. Must be present if MAC is used. | +| LANG | 2 | Language type | +| P\_SIGN | 1-256 | Merchant MAC in hexadecimal form. | +| NAME | 2-45 | Customer's name (as indicated on the card) | +| M\_INFO | 35000 | Must be a Base64-encoded string of JSON-formatted "parameter": "value data". | +| MERCH\_3D\_TERM\_URL | | MerchantURL where will return Cres response from client ACS. | +| CARD | 9-19 | Card number (Primary account number). | +| EXP | 02 | Card expiration month (Numeric 2 digit value). | +| EXP\_YEAR | 02 | Card expiration year (Numeric 2 digit value: 20XX) | +| CVC2 | 03 | Card verification code(last three digits on the signature panel). | +| CVC2\_RC | 01 | CVC2 reason code. values: +value="1" -CVC2 is present +value="0" -CVC2 is not provided +value="2"-CVC2 is illegible | + +Below is an example of data prepared for the M\_INFO field: + +"M\_INFO"="ewoiYnJvd3NlclNjcmVlbkhlaWdodCI6IjE5MjAiLAoiYnJvd3NlclNjcmVlbldpZHRoIjoiMTA4MCIsCiJicm93c2VyVFoiOiIwIiwKIm1vYmlsZVBob25lIiA6eyAiY2MiOiI5OTQiLCAic3Vic2NyaWJlciI6IjU1Nzc3Nzc3Nzc3IiB9Cn0=", + +Decoded format: +{"browserIP":"0.0.0.0","browserScreenHeight":"1920","browserScreenWidth":"1080","browserTZ":"0","mobilePhone":{"cc":"994","subscriber":"5077777777"}} + +M\_INFO Parameters description: + +browserScreenHeight - Total height of the Cardholder’s screen in pixels. + +browserScreenWidth - Total width of the Cardholder’s screen in pixels.in pixels. + +browserTZ - Time difference between UTC time and the Cardholder browser local time, in minutes. + +mobilePhone - The mobile phone number provided by the Cardholder. + +Request body should be like below: + +"AMOUNT"="xx", "CURRENCY"="AZN", "ORDER"="xxxxxxxxxxxx", "DESC"="xxxxxxxxxxx xxxx", "MERCH\_NAME"="xxxxx.xxx", "MERCH\_URL"="https://xxxxxxxxxx.xx/xxxx", "MERCH\_GMT"="+4", "TERMINAL"="xxxxxxxxx", "EMAIL"="xxxxx@xxxxx.xx", "TRTYPE"="x", "COUNTRY"="AZ", "TIMESTAMP"="xxxxxxxxxxxxxx", "NONCE"="xxxxxxxxxxxxxxx", "BACKREF"="https://xxxxxxxxxxx/xxxxxxxxxxx/xxxxxx", "M\_INFO"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "P\_SIGN"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "MERCH\_3D\_TERM\_URL"="xxxxxxxxxxxxxxxxxxxxxxxx", "CARD"="xxxxxxxxxxxxxxxxxxx", "EXP"="xx", "EXP\_YEAR"="xx", "CVC2"="xxx", "CVC2\_RC"="x", + +#### Response format + +| Fields | Size | Description | +| --- | --- | --- | +| TERMINAL | 8 | Echo from the request | +| TRTYPE | 2 | Echo from the request | +| ORDER | 6-20 | Echo from the request | +| AMOUNT | 1-12 | Amount authorized. Usually, will be equal to original amount plus acquirer’s fee. | +| CURRENCY | 3 | Echo from the request | +| ACTION | 1 | EGateway action code | +| | | §0 – Transaction successfully completed | +| | | §1 – Duplicate transaction detected | +| | | §2 – Transaction declined  | +| | | §3 – Transaction processing error | +| RC | 02 | Transaction response code (ISO-8583 Field 39) | +| APPROVAL | 06 | Client bank’s approval code (ISO-8583 Field 38). Can be empty if not provided by card management system. | +| RRN | 12 | Merchant bank’s retrieval reference number (ISO-8583 Field 37) | +| INT\_REF | 1-32 | E-Commerce gateway internal reference number | +| TIMESTAMP | 14 | E-Commerce gateway timestamp in GMT: YYYYMMDDHHMMSS | +| NONCE | 1-64 | E-Commerce gateway nonce value. Will be filled with 8-32 unpredictable random bytes in hexadecimal format. Will be present if MAC is used. | +| P\_SIGN | 1-256 | E-Commerce gateway MAC (Message Authentication Code) in hexadecimal form. Will be present if MAC is used. | + +1\. If the card was enrolled on 3DSecure and card supports 3DS method, additional card authentication will take place before Authorization Response, as follows. + +1.1 If client card supports ThreeDSMethod; as an answer to the post request to below URL testmpi will return an XML response. + +https://testmpi.3dsecure.az/cgi-bin/cgi\_link + +Example: + +` https://testacs.3dsecure.az/way4acs/threeDSMethodURL; eyJ0aHJlZURTTWV0aG9kTm90aWZpY2F0aW9uVVJMIjoiaHR0cHM6Ly90ZXN0bXBpLjNkc2VjdXJlLmF6L2NnaS1iaW4vY2dpX2xpbmsiLC J0aHJlZURTU2VydmVyVHJhbnNJRCI6IjZkYTllMDk4LWFmZGEtNGY5NC1iMTMxLTAxZGNhZDA4NDgzOCJ9 C https://testmpi.3dsecure.az/cgi-in/cgi_link; ` + +2\. At the next step `threeDSMethodData` value should be posted to url specified in `` field above as in the following example. + +Note: in header must send `"content-type"="application/x-www-form-urlencoded”` parameter. + +https://testacs.3dsecure.az/way4acs/threeDSMethodURL + +`threeDSMethodData:eyJ0aHJlZURTTWV0aG9kTm90aWZpY2F0aW9uVVJMIjoiaHR0cHM6Ly90ZXN0bXBpLjNkc2VjdXJlLmF6L2NnaS1iaW4vY2dpX2xpbmsiLC J0aHJlZURTU2VydmVyVHJhbnNJRCI6IjZkYTllMDk4LWFmZGEtNGY5NC1iMTMxLTAxZGNhZDA4NDgzOCJ9` + +Answer to this request should be ignored, if http=200 (ok) + +Example of postman request. + +![threeDSMethodData](https://developer.azericard.com/i/image1.png) + +3\. At the next step threeDSMethodData value and `threeDSMethodState=C` should be Posted to below URL as in the following example + +https://testmpi.3dsecure.az/cgi-bin/cgi\_link + +in header must send `"content-type"="application/x-www-form-urlencoded”` parameter. + +`threeDSMethodData:eyJ0aHJlZURTTWV0aG9kTm90aWZpY2F0aW9uVVJMIjoiaHR0cHM6Ly90ZXN 0bXBpLjNkc2VjdXJlLmF6L2NnaS1iaW4vY2dpX2xpbmsiLCJ0aHJlZURTU2VydmVyVHJhbnNJRCI6Ijc5Yz Y3ZWY4LTZhN2ItNDBlOS04ZDdjLWE5N2I5MzcyM2RmMiJ9 threeDSMethodState:C` + +Example screen from postman below + +![threeDSMethodState](https://developer.azericard.com/i/image2.png) + +If answer “WAITING” received, previous message should be resend until “CONTINUE” answer received or 10 seconds of such cycle exceeded. After receiving “CONTINUE” message or 10 sec time exceeded, whichever is the first, the same as above message with threeDSMethodState=N should be sent to URL:https://testmpi.3dsecure.az/cgi-bin/cgi\_link as in the following example to proceed, example is below: + +https://testmpi.3dsecure.az/cgi-bin/cgi\_link + +in header must send `"content-type"="application/x-www-form-urlencoded”` parameter. + +`threeDSMethodData:eyJ0aHJlZURTTWV0aG9kTm90aWZpY2F0aW9uVVJMIjoiaHR0cHM6Ly90ZXN 0bXBpLjNkc 2VjdXJlLmF6L2NnaS1iaW4vY2dpX2xpbmsiLCJ0aHJlZURTU2VydmVyVHJhbnNJRCI6Ijc5YzY3ZWY4LTZ hN2ItNDBlOS04ZDdjLWE5N2I5MzcyM2RmMiJ9 threeDSMethodState:N` + +4\. Response to this message will be an issuer ACS html page which should be answered to original customer session. Merchant must open mentioned HTML ACS page to customer and customer will be redirected to his issuer ACS system. + +5\. Client authenticates itself on this page. After client is authenticated, issuer ACS will post url specified in **Authorization Request** at MERCH\_3D\_TERM\_URL field (the merchant url). This post will contain CRES authentication response. Example of such post below. + +Example: + +`"cres":"eyJtZXNzYWdlVHlwZSI6IkNSZXMiLCJtZXNzYWdlVmVyc2lvbiI6IjIuMS4wIiwidGhyZWVEU1Nlc nZlclRyYW5zSUQiOiI3YTQ1NzhlNC1kNjk5LTQwN2EtODg2MS0zNDIwNTk0ZTk0MjkiLCJhY3NUcmFuc 0lEIjoiMGVhNzU3ODUtOTQ5OC00MjQ3LWEzYzctYzViY2FlMDk2NzU5IiwiY2hhbGxlbmdlQ29tcGxld GlvbkluZCI6IlkiLCJ0cmFuc1N0YXR1cyI6IlkifQ", "threeDSSessionData":"MDdhYTNiNDQtYzY0OC00YThiLThiOTktOTBiNDM3ZDc2MTI5"` + +1.5. This received Cres data response “as is” should be send (post) to MPI + +URL: + +https://testmpi.3dsecure.az/cgi-bin/cgi\_link + +Example:in POST cres request in header must be `content-type=x-www-form-urlencoded` parameter + +`cres:eyJtZXNzYWdlVHlwZSI6IkNSZXMiLCJtZXNzYWdlVmVyc2lvbiI6IjIuMS4wIiwidGhyZWVEU1Nlc nZlclRyYW5zSUQiOiI3YTQ1NzhlNC1kNjk5LTQwN2EtODg2MS0zNDIwNTk0ZTk0MjkiLCJhY3NUcmFuc 0lEIjoiMGVhNzU3ODUtOTQ5OC00MjQ3LWEzYzctYzViY2FlMDk2NzU5IiwiY2hhbGxlbmdlQ29tcGxld GlvbkluZCI6IlkiLCJ0cmFuc1N0YXR1cyI6IlkifQ threeDSSessionData:MDdhYTNiNDQtYzY0OC00YThiLThiOTktOTBiNDM3ZDc2MTI5` + +Example screen from postman below + +![threeDSSessionData](https://developer.azericard.com/i/image3.png) + +6\. As an answer to this MPI will send Authorization Response. +Example of response will contain below data’s + +` Approved 1111111 1 (can be 0) 20230621052514 1.00 944 0 00 111111 317276406077 0A7E21C778330DF2 20230621052514 7fdc0caafb113590 5dc32febbca757927aa353b526515b30a3ef4bf87a5ce24e4e01ad6292954560e97b3a30283fd034d3e5b6d21 ec72ce2a37db27a476ff970f7e5ae694b39b637101643f220f701f7918295d06c287c46ec8e6aa7e48e2d560c49 f76a09ccd0aa4404dd889e98c474f162f7154c95e5bd9c16333c4f0088f8a732c48fc902de9d9b782a7a07cd0aa 1a1d07852b1306b8185160cdc36d665e65ac9b63ca44700933a1e0bfba9624f08d86a4259fecf3a020d7ff254a0 7468881e05e3fe08f11624f5d235341965cc272e4360a27a0bbe8ad868952a0b4072b4a4239704712fa033989 35ab2527517672948c4ef2d4cb5a8e4e2381f7e3ef9d8c6ccb85d154b08fd ` + +2\. If the card was enrolled on 3DSecure and card does not support 3DS method, additional card authentication will take place before Authorization Response, as follows. + +1\. Response to Authorization Request message will be an issuer ACS html page should be answered to original customer session, customer will be redirected to his issuer ACS system. + +Example response of issuer ACS html form below. Merchant should open mentioned page to client. + +` ` + +2\. Client authenticates itself on this page. + +3\. After client authenticated, issuer ACS will post url specified in **Authorization Request** at MERCH\_3D\_TERM\_URL field. This post will contain CRES authentication response. Example of such post below. + +Example: + +`"cres":"eyJtZXNzYWdlVHlwZSI6IkNSZXMiLCJtZXNzYWdlVmVyc2lvbiI6IjIuMS4wIiwidGhyZWVEU1Nlc nZlclRyYW5zSUQiOiI3YTQ1NzhlNC1kNjk5LTQwN2EtODg2MS0zNDIwNTk0ZTk0MjkiLCJhY3NUcmFuc 0lEIjoiMGVhNzU3ODUtOTQ5OC00MjQ3LWEzYzctYzViY2FlMDk2NzU5IiwiY2hhbGxlbmdlQ29tcGxld GlvbkluZCI6IlkiLCJ0cmFuc1N0YXR1cyI6IlkifQ", "threeDSSessionData":"MDdhYTNiNDQtYzY0OC00YThiLThiOTktOTBiNDM3ZDc2MTI5"` + +This received Cres data response “as is” should be send (post) to MPI: + +https://testmpi.3dsecure.az/cgi-bin/cgi\_link + +Example:in POST cres request in header must be `content-type=x-www-form-urlencoded` parameter + +`cres:eyJtZXNzYWdlVHlwZSI6IkNSZXMiLCJtZXNzYWdlVmVyc2lvbiI6IjIuMS4wIiwidGhyZWVEU1Nlc nZlclRyYW5zSUQiOiI3YTQ1NzhlNC1kNjk5LTQwN2EtODg2MS0zNDIwNTk0ZTk0MjkiLCJhY3NUcmFuc 0lEIjoiMGVhNzU3ODUtOTQ5OC00MjQ3LWEzYzctYzViY2FlMDk2NzU5IiwiY2hhbGxlbmdlQ29tcGxld GlvbkluZCI6IlkiLCJ0cmFuc1N0YXR1cyI6IlkifQ threeDSSessionData:MDdhYTNiNDQtYzY0OC00YThiLThiOTktOTBiNDM3ZDc2MTI5` + +![threeDSSessionData](https://developer.azericard.com/i/image3.png) + +4.As an answer to this MPI will send Authorization Response.Example of response will contain below data’s + +` Approved 1111111 1 (can be 0) 20230621052514 1.00 944 0 00 111111 317276406077 0A7E21C778330DF2 20230621052514 7fdc0caafb113590 5dc32febbca757927aa353b526515b30a3ef4bf87a5ce24e4e01ad6292954560e97b3a30283fd034d3e5b6d21 ec72ce2a37db27a476ff970f7e5ae694b39b637101643f220f701f7918295d06c287c46ec8e6aa7e48e2d560c49 f76a09ccd0aa4404dd889e98c474f162f7154c95e5bd9c16333c4f0088f8a732c48fc902de9d9b782a7a07cd0aa 1a1d07852b1306b8185160cdc36d665e65ac9b63ca44700933a1e0bfba9624f08d86a4259fecf3a020d7ff254a0 7468881e05e3fe08f11624f5d235341965cc272e4360a27a0bbe8ad868952a0b4072b4a4239704712fa033989 35ab2527517672948c4ef2d4cb5a8e4e2381f7e3ef9d8c6ccb85d154b08fd ` + +3\. If the card supports frictionless authentication. During the authorization the Frictionless Flow does not require further Cardholder interaction to achieve a successful authentication and complete the 3-D Secure authentication process. + +3.1. As an answer to this MPI will send Authorization Response.Example of response will contain below data’s + +` Approved 1111111 1 (can be 0) 20230621052514 1.00 944 0 00 111111 317276406077 0A7E21C778330DF2 20230621052514 7fdc0caafb113590 5dc32febbca757927aa353b526515b30a3ef4bf87a5ce24e4e01ad6292954560e97b3a30283fd034d3e5b6d21 ec72ce2a37db27a476ff970f7e5ae694b39b637101643f220f701f7918295d06c287c46ec8e6aa7e48e2d560c49 f76a09ccd0aa4404dd889e98c474f162f7154c95e5bd9c16333c4f0088f8a732c48fc902de9d9b782a7a07cd0aa 1a1d07852b1306b8185160cdc36d665e65ac9b63ca44700933a1e0bfba9624f08d86a4259fecf3a020d7ff254a0 7468881e05e3fe08f11624f5d235341965cc272e4360a27a0bbe8ad868952a0b4072b4a4239704712fa033989 35ab2527517672948c4ef2d4cb5a8e4e2381f7e3ef9d8c6ccb85d154b08fd ` + +4\. If card supports 3DS method and not enrolled on 3D service need to do 1.1, 1.2, 1.3 actions and As an answer to this MPI for Authorization will response with Authentication failed message like below. +Example of response will contain below data’s + +` Authentication failed 1111111 1 (can be 0) 20230621052514 1.00 944 3 -19 20230621052514 7fdc0caafb113590 5dc32febbca757927aa353b526515b30a3ef4bf87a5ce24e4e01ad6292954560e97b3a30283fd034d3e5b6d21 ec72ce2a37db27a476ff970f7e5ae694b39b637101643f220f701f7918295d06c287c46ec8e6aa7e48e2d560c49 f76a09ccd0aa4404dd889e98c474f162f7154c95e5bd9c16333c4f0088f8a732c48fc902de9d9b782a7a07cd0aa 1a1d07852b1306b8185160cdc36d665e65ac9b63ca44700933a1e0bfba9624f08d86a4259fecf3a020d7ff254a0 7468881e05e3fe08f11624f5d235341965cc272e4360a27a0bbe8ad868952a0b4072b4a4239704712fa033989 35ab2527517672948c4ef2d4cb5a8e4e2381f7e3ef9d8c6ccb85d154b08fd ` + +5\. If card doesn’t supports 3DS method and not enrolled on 3D. During the Authorization MPI will send Authorization Response like Authentication failed message like below. +Example of response will contain below data’s + +` Authentication failed 1111111 1 (can be 0) 20230621052514 1.00 944 3 -19 20230621052514 7fdc0caafb113590 5dc32febbca757927aa353b526515b30a3ef4bf87a5ce24e4e01ad6292954560e97b3a30283fd034d3e5b6d21 ec72ce2a37db27a476ff970f7e5ae694b39b637101643f220f701f7918295d06c287c46ec8e6aa7e48e2d560c49 f76a09ccd0aa4404dd889e98c474f162f7154c95e5bd9c16333c4f0088f8a732c48fc902de9d9b782a7a07cd0aa 1a1d07852b1306b8185160cdc36d665e65ac9b63ca44700933a1e0bfba9624f08d86a4259fecf3a020d7ff254a0 7468881e05e3fe08f11624f5d235341965cc272e4360a27a0bbe8ad868952a0b4072b4a4239704712fa033989 35ab2527517672948c4ef2d4cb5a8e4e2381f7e3ef9d8c6ccb85d154b08fd ` + +**Note:**Payment confirmation, refund and calculation of P\_SIGN value are same as in E-commerce integration method. + +## 3 Installment + +During the installation service, in addition to the parameters shown above [(Switch link)](#integration) , the following parameter is posted to the appropriate url address. To perform installment operations, the ACQ\_INST\_PAYIN parameter is posted in the query and the INST\_ALL\* (\*=3,6,9,12,18,24,27,30) installment numbers are sent according to the number of installments. + +### For installment + +| Fields | Size | Description | +| --- | --- | --- | +| ACQ\_INST\_PAYIN | 9 - 10 | INST\_ALL\* (\*=3,6,9,12,18,24,27,30) | + +### Non installment + +| Fields | Size | Description | +| --- | --- | --- | +| ACQ\_INST\_PAYIN | 9-10 | INST\_ALL\* (\*= X) | + +### Response format + +Success response: `INST_ALL*` + +| Kod | Xəta | Description | +| --- | --- | --- | +| U1 | Empty instalment configuration | No entries (no rows at all) in the BinRangeFile | +| U2 | Invalid instalment configuration | Number of fields in the BinRangeFile is not equal to 3 | +| U3 | Card BIN range not found | No BIN range matched the provided PAN | +| U4 | No instalments configured for the BIN range | BIN range matched, but no instalments configured for the range | +| U5 | No instalments configured for the terminal | Terminal configuration AcqInstTypeList is empty | +| U6 | Selected instalment not configured for the terminal | | +| U7 | Selected instalment not configured for the BIN range | | + +## 4 Test data + +This is the test environment, where you can do test transactions and simulate results (approved, declined). It’s usage is recommended while you are developing and testing your integration. In test environment you will use test keys generated by AZC and test data placed on website. + +### 4.1 Test card + +For transaction with test card number you should use the following card data. + +
PAN4127208104942601
EXP_MONTH05
EXP_YEAR31
CVV796
SMS One Time Password1111
+ +
PAN5167513332880780
EXP_MONTH05
EXP_YEAR31
CVV609
SMS One Time Password1111
+ +
PAN4127214121630724
EXP_MONTH04
EXP_YEAR31
CVV536
SMS One Time Password1111
Card NameTam Card Visa (ABB müştərilərinə)
+ +### 4.2 Test terminal + +For transaction with test terminal you should use the following terminal id. + +
Terminal IDIt will be presented during integration
+ +### 4.3 Test keys + +In the test environment, you will be presented with 1 Azericard public key (Public RSA). Generation of keys is mentioned in paragraph 4. [Link](#generateKeys) + +
MPI Public KeyIt will be presented during integration
+ +#### Calculation of callback P_SIGN { #callbackCalc } + +The following variables are used to calculate callback P\_SIGN. Additionally, if the value of any of the specified variables is sent empty, then a - (hyphen) sign is added instead of that value, and its length is ignored in the P\_SIGN part. + +| Fields | Size | Description | +| --- | --- | --- | +| AMOUNT | 1-12 | Order total amount in float format with decimal point separator | +| TERMINAL | 8 | Merchant Terminal ID assigned by bank | +| APPROVAL | 6 | Client bank’s approval code (ISO-8583 Field 38). Can be empty if not provided by card management system. | +| RRN | 12 | Merchant bank’s retrieval reference number (ISO-8583 Field 37) | +| INT\_REF | 1-32 | Internal reference number from authorization response. | + +## 5 Key generation process { #generateKeys } + +In production system merchant should generate and give his public key to Azericard and Azericard will give his public key to merchant. Private keys must be private for each side (merchant/Azericard). Generating Public and Private RSA Keys from Merchant side: + +To perform the following actions for Windows or Linux, you must have OpenSSL installed on your system. + +### 5.1 Generating the private key(Windows) + +1\. Open the Command Prompt: + +Start > Programs > Accessories > Command Prompt. + +2\. Navigate to the following folder: + +C:\\Program Files\\ListManager\\tclweb\\bin\\certs + +3\. Type the following: + +openssl genrsa -out merchant\_name\_private\_key.pem 2048 + +4\. Press ENTER. + +The private key is generated and saved in a file named 'merchant\_name\_private\_key .pem' located in the same folder. + +### 5.2 Generating the public key(Windows) + +1\. At the command prompt, type the following: + +openssl rsa -in merchant\_name\_private\_key.pem -pubout -out merchant\_name\_public\_key.pem + +2\. Press ENTER. + +The public key saved in a file named merchant\_name\_public\_key .pem located in the same folder. + +### 5.3 Generating the private key(Linux) + +1\. Open the Terminal. + +2\. Type the following: + +openssl genrsa -out merchant\_name\_private\_key.pem 2048 + +4\. Press ENTER. + +The private key is generated and saved in a file named 'merchant\_name\_private\_key .pem' located in the same folder. + +### 5.4 Generating the public key(Linux) + +1\. Open the Terminal. + +2\. Type the following: + +openssl rsa -in merchant\_name\_private\_key.pem -pubout -out merchant\_name\_public\_key.pem + +3\. Press ENTER. + +The public key is saved in a file named merchant\_name\_public\_keypem located in the same folder. + +## 6 Card storage + +Above during card storage service ([Link](#integration)) in addition to the specified parameters, the parameter mentioned below is posted to the corresponding url address + +[https://testmpi.3dsecure.az/token/cgi\_link](https://testmpi.3dsecure.az/token/cgi_link) + +### 6.1 Card save integration + +| Fields | Size | Description | +| --- | --- | --- | +| TOKEN\_ACTION | 8 | REGISTER + +The parameter must be posted when storing the token | +| MERCH\_TRAN\_STATE | 1 | Authorization initiation indicator +value = 'S' | + +When storing the card, the merchant must post the TOKEN\_ACTION=REGISTER parameter in the request. To save the card, the merchant must make a successful payment, even if it is a minimal amount. After the payment is completed, the following parameters will be sent to the callback address provided by the merchant. + +"AMOUNT"="xx", "CURRENCY"="AZN", "ORDER"="xxxxxxxxxxxx", "ACTION"="xxxxx", "RC"="xxx", "APPROVAL"="xxx", "RRN"="xxx", "INT\_REF"="xxxxxxxx", "EMAIL"="xxxxxxxx", "CARD"="xxxxxxxx", "TOKEN"="xxxxxxxx", "TERMINAL"="xxxxxxxxx", "TRTYPE"="x", "TIMESTAMP"="xxxxxxxxxxxxxx", "NONCE"="xxxxxxxxxxxxxxx", "P\_SIGN"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +### 6.2 Payment by stored card + +| Fields | Size | Description | +| --- | --- | --- | +| TOKEN | 28 | TOKEN parameter of saved card | + +When paying with a stored card, the merchant must post the TOKEN parameter received in the request callback. After the payment is completed, the following parameters will be sent to the callback address provided by the merchant. +NOTE: The TOKEN\_ACTION=REGISTER parameter should not be posted for saved card payments. + +"AMOUNT"="xx", "CURRENCY"="AZN", "ORDER"="xxxxxxxxxxxx", "ACTION"="xxxxx", "RC"="xxx", "APPROVAL"="xxx", "RRN"="xxx", "INT\_REF"="xxxxxxxx", "EMAIL"="xxxxxxxx", "CARD"="xxxxxxxx", "TOKEN"="xxxxxxxx", "TERMINAL"="xxxxxxxxx", "TRTYPE"="x", "TIMESTAMP"="xxxxxxxxxxxxxx", "NONCE"="xxxxxxxxxxxxxxx", "P\_SIGN"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +### 6.3 CIT Payment + +| Fields | Size | Description | +| --- | --- | --- | +| MERCH\_TRAN\_STATE | 1 | Authorization initiation indicator +value = 'C' | +| TOKEN | 28 | Value returned to the merchant during card storage | + +When storing the card, the merchant must post the TOKEN\_ACTION=REGISTER parameter in the request. To save the card, the merchant must make a successful payment, even if it is a minimal amount. After the payment is completed, the following parameters will be sent to the callback address provided by the merchant. + +"AMOUNT"="xx", "CURRENCY"="AZN", "ORDER"="xxxxxxxxxxxx", "ACTION"="xxxxx", "RC"="xxx", "APPROVAL"="xxx", "RRN"="xxx", "INT\_REF"="xxxxxxxx", "EMAIL"="xxxxxxxx", "CARD"="xxxxxxxx", "TOKEN"="xxxxxxxx", "TERMINAL"="xxxxxxxxx", "TRTYPE"="x", "TIMESTAMP"="xxxxxxxxxxxxxx", "NONCE"="xxxxxxxxxxxxxxx", "P\_SIGN"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +## 7 Recurring + +Above during card storage service ([Link](#integration)) in addition to the specified parameters, the parameter mentioned below is posted to the corresponding url address + +[https://testmpi.3dsecure.az/token/cgi\_link](https://testmpi.3dsecure.az/token/cgi_link) + +### 7.1 MIT Unscheduled – Cardsave + +| Fields | Size | Description | +| --- | --- | --- | +| MERCH\_TRAN\_STATE | 1 | Authorization initiation indicator +value = 'S' | +| TOKEN\_ACTION | 8 | REGISTER | +| MERCH\_RN\_ID | 16 | Merchant nonce. Must be generated using 8–32 random bytes and represented in hexadecimal format. Must be considered when MAC is used. | +| MIT\_AGREEMENT | 1 | Indicates whether a payment agreement exists with the cardholder for Merchant-Initiated Transactions. +value = 'N' | +| TRTYPE | 1 | Transaction type = 1 (Finance document) | + +After sending the request, the following response is returned. Save the EXT\_NET\_REF parameters. For this, you must specify EXT\_NET\_REF. If the EXT\_NET\_REF value is not returned in the response to the card storage request, then there is no need to send the parameter during payment + +"AMOUNT"="xx", "CURRENCY"="AZN", "ORDER"="xxxxxxxxxxxx", "ACTION"="xxxxx", "RC"="xxx", "APPROVAL"="xxx", "RRN"="xxx", "INT\_REF"="xxxxxxxx", "EMAIL"="xxxxxxxx", "CARD"="xxxxxxxx", "TOKEN"="xxxxxxxx", "TERMINAL"="xxxxxxxxx", "TRTYPE"="x", "TIMESTAMP"="xxxxxxxxxxxxxx", "NONCE"="xxxxxxxxxxxxxxx", "P\_SIGN"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "EXT\_NET\_REF"="xxxxxxxxxxxxxxxxxxxxx" + +### 7.2 MIT Unscheduled – Payment + +| Fields | Size | Description | +| --- | --- | --- | +| MERCH\_TRAN\_STATE | 1 | Authorization initiation indicator +value = 'M' | +| EXT\_NET\_REF | 6-32 | Value returned to the merchant during card storage | +| MERCH\_RN\_ID | 16 | Merchant nonce. Must be generated using 8–32 random bytes and represented in hexadecimal format. Must be considered when MAC is used. | +| TOKEN | 28 | Value returned to the merchant during card storage | +| TRTYPE | 1 | Transaction type = 1 (Finance document) | + +### 7.3 MIT Scheduled – Cardsave + +| Fields | Size | Description | +| --- | --- | --- | +| MERCH\_TRAN\_STATE | 1 | Authorization initiation indicator +value = 'S' | +| TOKEN\_ACTION | 8 | REGISTER | +| MERCH\_RN\_ID | 16 | Merchant nonce. Must be generated using 8–32 random bytes and represented in hexadecimal format. Must be considered when MAC is used. | +| MIT\_AGREEMENT | 1 | Indicates whether a payment agreement exists with the cardholder for Merchant-Initiated Transactions. +value = 'Y' | +| TRTYPE | 1 | Transaction type = 1 (Finance document) | +| RECUR\_FREQ | 2 | Minimum time interval between authorizations (charges). Numeric format. (Example: 11) | +| RECUR\_EXP | 8 | Expiration date of the subscription in YYYYMMDD format. The subscription may last up to 1 year from the card registration date. | + +After sending the request, the following response is returned. Save the EXT\_NET\_REF parameters. For this, you must specify EXT\_NET\_REF. If the EXT\_NET\_REF value is not returned in the response to the card storage request, then there is no need to send the parameter during payment + +"AMOUNT"="xx", "CURRENCY"="AZN", "ORDER"="xxxxxxxxxxxx", "ACTION"="xxxxx", "RC"="xxx", "APPROVAL"="xxx", "RRN"="xxx", "INT\_REF"="xxxxxxxx", "EMAIL"="xxxxxxxx", "CARD"="xxxxxxxx", "TOKEN"="xxxxxxxx", "TERMINAL"="xxxxxxxxx", "TRTYPE"="x", "TIMESTAMP"="xxxxxxxxxxxxxx", "NONCE"="xxxxxxxxxxxxxxx", "P\_SIGN"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "EXT\_NET\_REF"="xxxxxxxxxxxxxxxxxxxxx" + +### 7.4 MIT Scheduled – Payment + +| Fields | Size | Description | +| --- | --- | --- | +| EXT\_NET\_REF | 6-32 | Value returned to the merchant during card storage | +| TOKEN | 28 | Value returned to the merchant during card storage | +| TRTYPE | 3 | 185 | + +## 8 Transaction Status + +### 8.1 Check transaction status + +Merchant can send transaction status request to E-commerce gateway during 24h from transaction request time. + +To our E-commerce gateway need send HTTP POST request to URL: + +https://testmpi.3dsecure.az/cgi-bin/cgi\_link + +#### Request format + +| Fields | Size | Description | +| --- | --- | --- | +| TRAN\_TRTYPE | 1-2 | Original transaction type for state request (For example: TRTYPE 0, 1, 22, 24 and etc.) | +| ORDER | 6-20 | Original transaction order id for state request | +| TERMINAL | 8 | Merchant Terminal ID assigned by bank | +| TRTYPE | 2 | Must be equal to "90" (Transaction request type). | +| TIMESTAMP | 14 | Merchant transaction timestamp in GMT: YYYYMMDDHHMMSS. Timestamp difference between merchant server and e-Gateway server must not exceed 1 hour, otherwise e-Gateway will reject this transaction. | +| NONCE | 1-64 | Merchant nonce. Must be filled with 8-32 unpredictable random bytes in hexadecimal format. Must be present if MAC is used. | +| P\_SIGN | 1-256 | Merchant MAC in hexadecimal form. | + +### 8.2 Response can be in HTML, XML and JSON format according to Merchant request. + +| Fields | Description | +| --- | --- | +| ACTION | Original transaction action for state request | +| Response code | Original transaction RC for state request | +| Transaction Status message | Original transaction status message | +| TERMINAL | Original transaction Terminal ID | +| Card number | Original transaction masked card number | +| Transaction amount | Original transaction amount | +| Transaction currency | Original transaction currency | +| Transaction date | Original transaction date | +| Transaction state | Original transaction state | +| Merchant order id | Original transaction ORDER ID | +| Banks approval code | Original transaction approval code | +| Transaction RRN | Original transaction RRN | +| INT\_REF | Original transaction INT\_REF | +| Original transaction TRTYPE | Original transaction TRTYPE | +| Timestamp | Request Timestamp | +| Nonce | Original transaction Nonce | +| P\_SIGN | E-Commerce gateway MAC (Message Authentication Code) in Hexadecimal form. Will be present if MAC is used. | + +### 8.3 Merchant MAC – Message Authentication Code + +To authenticate transaction messages on gateway to/from the merchant link, the merchant system should be able to calculate and verify message authentication codes for at least the transactions passed through cardholder browser redirects. Messages that are sent directly to e-Commerce Gateway (“Sales completion” and “Reversal”) may be mutually authenticated with SSL client/server certificates and does not require MAC; if they are not mutually authenticated, MAC for these messages is mandatory. + +MAC is calculated over all fields generated by the merchant system as defined in corresponding format Tables (visible and hidden fields generated by the merchant system) except the MAC field (“P\_SIGN”) itself. + +In order to generate or verify the message authentication field, the merchant system must assemble a MAC source string; all field values from the format tables are prefixed with the decimal field length in ASCII and concatenated in a specified order. If the field is not present, the '-' character is added to the message in its place. + +Authorization message example: MAC source string will contain the following field values - ORDER, TERMINAL, TRTYPE, TIMESTAMP and NONCE. Suppose that we have a transaction with following fields: + +| Fields | Size | Value | +| --- | --- | --- | +| ORDER | 14 | 20211112075614 | +| TERMINAL | 8 | 17202191 | +| TRTYPE | 2 | 90 | +| TIMESTAMP | 14 | 20211112075714 | +| NONCE | 16 | 7cfb4c2512eeec72 | + +`14`20211112075614`8`17202191`2`90`14`20211112075714`16`7cfb4c2512eeec72 + +Line breaks are inserted for visibility only. This string is 190 bytes long + +After the MAC source string is assembled, the merchant system must apply a cryptographic algorithm to generate the message authentication code. Gateway supports various cryptographic algorithms and the system administrator may specify which algorithm will be used for a particular merchant terminal. + +The merchant system must implement a chosen algorithm either in hardware or software form and be fully responsible for the secure storage and usage of corresponding cryptographic keys. An effective key length must be at least 112 bits for asymmetric cryptographic algorithms and 2048 bits for RSA with SHA256 algorithm. + +The default MAC algorithm is RSAwithSHA256. Additional options may be available on demand. For our MAC source string example and HMAC RSA with SHA256 algorithm with Private RSA key the result MAC (“P\_SIGN”) field must be equal to: + +`“5dc32febbca757927aa353b526515b30a3ef4bf87a5ce24e4e01ad6292954560e97b3a30283fd034d3e5b6d21 ec72ce2a37db27a476ff970f7e5ae694b39b637101643f220f701f7918295d06c287c46ec8e6aa7e48e2d560c49 f76a09ccd0aa4404dd889e98c474f162f7154c95e5bd9c16333c4f0088f8a732c48fc902de9d9b782a7a07cd0aa 1a1d07852b1306b8185160cdc36d665e65ac9b63ca44700933a1e0bfba9624f08d86a4259fecf3a020d7ff254a0 7468881e05e3fe08f11624f5d235341965cc272e4360a27a0bbe8ad868952a0b4072b4a4239704712fa033989 35ab2527517672948c4ef2d4cb5a8e4e2381f7e3ef9d8c6ccb85d154b08fd”` + +MAC field value can be either an upper case or lower case hexadecimal string. + +## 9 GooglePay Acquiring Service Integration + +"Azericard" LLC is the first processing centre in the Republic of Azerbaijan, completely certified by International Payment Systems: MasterCard, Visa, American Express, Diners Club, UnionPay and JCB. AzeriCard performs processing for15 bank in Azerbaijan and abroad, all of them are the members of International Payment Systems. Azericard actively implements state-of-the-art technological projects such as payments for telecom services and public utilities, customs and tax payments, Internet and Mobile Banking, Card-to-Card transfers (Kart Transfer, VISA Direct, MasterCard Money Send), VTS, insurance and deposit payments via ATMs, different loyalty programs, multicurrency card and so on. + +This document provides merchants and their affiliates with the tools to integrate Azericard Google Pay Interface so that Azericard may process their transaction requests. + +#### GOOGLEPAY™APIWEB INTEGRATION + +#### Accept payments without entering card details. + +Google Pay™ is a digital wallet, which enables simple and fast card payments, without the need to enter the card data for each payment. The card data is safely stored by Google. This payment method is available for all devices (mobile phones and computers), irrespective of the operating system and web browser.In case of Google Pay usage, Acceptor is obligated to comply with the provisions of the following [regulations](https://payments.developers.google.com/terms/sellertos) + +#### Authorization methods + +- PAN\_ONLY: This authentication method is associated with payment cards stored on file with the user's Google Account.Returned payment data includes personal account number(PAN) with the expiration month and the expiration year. +- CRYPTOGRAM\_3DS: This authentication method is associated with cards stored as Android device tokens.Returned payment data includes a 3-D Secure(3DS) cryptogram generated on the device. + +The authorization methods allowed with GooglePay ™ are by card and by 3D Secure cryptogram. For more information about the authorized authorization methods consult the [official Google™ documentation](https://developers.google.com/pay/api/web/reference/request-objects#CardParameters) + +#### Accepted cards + +The cards that are allowed for these payment methods are: + +- VISA +- MASTERCARD +- AMEX +- JCB +- DCI + +#### Documentation links for integration: + +Android: [https://developers.google.com/pay/api/android/overview?hl=en](https://developers.google.com/pay/api/android/overview?hl=en) + +Web: [https://developers.google.com/pay/api/web/overview?hl=en](https://developers.google.com/pay/api/web/overview?hl=en) + +Design Guideline: [https://developers.google.com/pay/api/web/guides/brand-guidelines?hl=en](https://developers.google.com/pay/api/web/guides/brand-guidelines?hl=en) + +Google Pay and Wallet APIs Acceptable Use Policy: [https://payments.developers.google.com/terms/aup?hl=en](https://payments.developers.google.com/terms/aup?hl=en) + +Google Pay API Terms of Service: [https://payments.developers.google.com/terms/sellertos](https://payments.developers.google.com/terms/sellertos) + +The gateway parameter in the script should have the constant value of **Azericard**, according to the example below: + +1. Add Google Pay Button for get payment data. +2. Merchant receives the payment data from Google. +3. Merchant generate payment request to Azericard gateway. +4. Merchant receive payment data from Azericard gateway. +5. Merchant displays payment status to consumer. + +#### Example code for displaying Google Pay button + +``` +; + +``` + +**allowedAuthMethods** - Azericard can process both PAN\_ONLY and CRYPTOGRAM\_3DS authentication methods. + +**allowedCardNetworks** - specify the card networks that you wish to allow. If the customer has cards in their wallet that are not in the 'allowed' list then those cards will be greyed-out/disabled in their wallet. + +**merchantId** - found in the Google Pay Business Console under your account's Public merchant profile setting. Please note that this is only required in Google Pay's production environment; while testing, this field can be set to a dummy value or omitted. + +**gateway** - a unique property that identifies Azericard as the processor; all encryption keys are associated with this ID. This field value provided by Azericard. + +**gatewayMerchantId** - a property that uniquely identifies the merchant. This field value provided by Azericard. + +#### Request Example to Azericard Payment Gateway. + +**Request URL**: [https://testmpi.3dsecure.az/cgi-bin/cgi\_link](https://testmpi.3dsecure.az/cgi-bin/cgi_link) + +**CONTENT-TYPE**: x-www-form-urlencoded + +Request Parameters: + +| Fields | Size | Description | +| --- | --- | --- | +| AMOUNT | 1-12 | Order total amount Required Float with decimal point separator | +| CURRENCY | 3 | Order currency Required Alphabetic, \[A-Z\] | +| ORDER | 6-20 | Merchant order ID Required Integer Last 6 digits used as system trace audit number and must be unique within a day for the terminal ID | +| DESC | 2 | This document describes the ApplePay & GPay Acquiring service details and the integration procedure between the Azericard Apple/GPay service and the merchants or banks’ mobile applications. | +| MERCH\_URL | 1-250 | Merchant primary website URL Required | +| TERMINAL | 8 | Merchant terminal ID assigned by bank Required | +| TRTYPE | 1 | Transaction type Required Integer Possible values: 1 – purchase | +| TIMESTAMP | 14 | Merchant transaction timestamp in GMT (GMT time zone offset 0) Required Integer, YYYYMMDDHHMMSS Discrepancy between merchant and gateway servers should not exceed 1 hour, otherwise, the transaction will be declined. | +| NONCE | 1-64 | Merchant nonce Conditional Hexadecimal, 8-32 unpredictable random bytes Required if MAC is used | +| P\_SIGN | 1-256 | Merchant MAC Required Hexadecimal | +| ADDENDUM | 2 | Optional Possible values: AD | +| AD.ECOM\_PAY\_DTLS | | Optional | +| GPAYTOKEN | 8-9 | Received paymentToken | + +#### HTTP POST Data: + +"AMOUNT"="1.00", + +"CURRENCY"="AZN", + +"ORDER"="123456", + +"DESC"="Some Record", + +"TERMINAL"="77777777", + +"TRTYPE"="1", + +"ADDENDUM"="AD", + +"AD.ECOM\_PAY\_DTLS"=" Some Record", + +"MERCH\_URL"="https://merchantURL.com", + +"NONCE"="3403fcef17df3c1c", + +"TIMESTAMP"="20250123044608", + +"P\_SIGN"="3641aa45289d8801d47de2f2dc5a88830b1dd72136082309cbef4adad75b17cf91da23a1948c 12e71cd866b8cd6213217e8f68c24f54dfee5826fbd9da4ec18d2b343587db5683f134ac1c5638271c2039 720701152fa0f28bc72eecda23973d8cb96e0779ad1fab488f1d13a08ebc413991c1913b8e17d8dda11f7c 699e23f0db90bf2ba832f805bc91ce7886b4e1d6b45181d0d4aca7b10c1a312a4b300c613f80f7fc7b2495c 2c20f4e8d3e83574abc4e94079575f57a6293d0b438398b7f7c0a63ccd23a180bfda18c99765528c4a55ace 8fcaa18babed0fb56dbbad0346309f8ff11948285f8ad64f24fd17b8a08fc4f116bae531ba45e346fe5dacec4 a" + +"GPAYTOKEN"="{"signature":"MEYCIQDHIUKOq6QqJPx9dFYaLHBKA9aTUdDXujcg3GKmeSZKXAIhAI50BC eNNxKBGu/71RteOqqc+R+iBfRlZMYKftJnXKB+","intermediateSigningKey":{"signedKey":"{\\"keyValue\\":\\ "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELCtHG9bjtMWCu4Iv4Td6npa/DiKc3Fou5R0bX2dk7tzEp+m byu3RJu+6epmmVwkHC5SbTztme9qk/kT65tpGiA\\=\\=\\",\\"keyExpiration\\":\\"1738277361000\\"}","signat ures":\["MEUCIEE+ADhhucm6jrwyn1UxqFLAGI3zHDp/XgpLGSuqPcemAiEAtuLPNLlPfl2uJzvlAYmouI6wT7y /akSlL5SEPVW+iXE="\]},"protocolVersion":"ECv2","signedMessage":"{\\"encryptedMessage\\":\\"AnnDsgE3 CaFKzQ2OEBJgg3f/2NnVF4gL6V1EbwLpJW4CCj2gvH7IKJFbHcYtofIT9JiiweTmalniMPpsfQiMgOcLT/Al4a7/ YNLkZrPYLO5g6G/qfsPfhWmlVHp6s3kistOvWmB8x2tCWaRa5XDQT4xs+PVzdd5Sv6aE0MN99zLw2fRcnYxi jqbD7DsVx3cW55LnGc2Hu/s2U/ExQp+/5Nqn2LNJQhMP03DS1kFv0r0dxlKkmYMv5VPVyKkrvPtCdc63W0 3tdCdJID6bDS6sb60C9n1Md/h92t6WX6T/XlyKmbsGcWb9Yqxx0h0AMBa4KY/jBMeSZc1Hsz/hIWZSLp+jFb pgiU4seBTA9cNeHswzb8T/gjffOM2rE/32v6UMKk+3Z8GTLoaYUYEIvv1MfY6fqkrOngqIw0iABi3NDrXBi5om v1p/IuRrOHNM/R9rybtAKNJcgSi0u9W90XeQxzWSISl49fUa8DEKjLXZNKFxg9w2J12mUNShfyfYu17+0h8ilik JZJPvB4r3CvjxueX6INpiMLixiSW8qSRARWbgh0inzRBpwolbi+pFD6nIAOHgzUDXGdlsGvW15KF/Td93fVsCB P9RUtD3dnbWVZWIyvzKGs6A3igtO7PgCxEPGvF02ubZq2awW8APXN2i\\",\\"ephemeralPublicKey\\":\\"BINi T+HhksaGzpP1Z2uCCWYNTW6dIG2cyDpcdhGh5FMN1da/kD2977KEIbXnJb0L2B5XGq0KpCEEgUPX4FGNY GQ\\=\\",\\"tag\\":\\"5lUVCC+Y+nvT/nsVNi8ZVnm8OCIQib8+z5EvN9z2gjM\\=\\"}"}", + +#### Example of Authorization Response: + +| Fields | Size | Description | +| --- | --- | --- | +| TERMINAL | 8 | Echo from the request | +| TRTYPE | 2 | Echo from the request | +| ORDER | 6-20 | Echo from the request | +| AMOUNT | 1-12 | Amount authorized. Usually, will be equal to original amount plus aquirer’s fee. | +| CURRENCY | 3 | Echo from the request | +| ACTION | 1 | Е-Gateway action code: +0 – Transaction successfully completed; +1 – Duplicate transaction detected; +2 – Transaction declined; +3 – Transaction processing fault. | +| RC | 2 | Transaction response code (ISO-8583 Field 39) | +| APPROVAL | 6 | Client bank’s approval code (ISO-8583 Field 38). Can be empty if not provided by card management system. | +| RRN | 12 | Merchant bank’s retrieval reference number (ISO-8583 Field 37). | +| INT\_REF | 1-32 | E-Commerce gateway internal reference number | +| TIMESTAMP | 14 | E-Commerce gateway timestamp in GMT: YYYYMMDDHHMMSS | +| NONCE | 1-64 | E-Commerce gateway nonce value. Will be filled with 8-32 unpredictable random bytes in hexadecimal format. Will be present if MAC is used. | +| P\_SIGN | 1-256 | E-Commerce gateway MAC (Message Authentication Code) in hexadecimal form. Will be present if MAC is used. | + +#### Merchant MAC – Message Authentication Code + +To authenticate transaction messages on gateway to/from the merchant link, the merchant system should be able to calculate and verify message authentication codes for at least the transactions passed through cardholder browser redirects. Messages that are sent directly to e-Commerce Gateway (“Sales completion” and “Reversal”) may be mutually authenticated with SSL client/server certificates and does not require MAC; if they are not mutually authenticated, MAC for these messages is mandatory. + +MAC is calculated over all fields generated by the merchant system as defined in corresponding format tables (visible and hidden fields generated by the merchant system) except the MAC field (“P\_SIGN”) itself. + +In order to generate or verify the message authentication field, the merchant system must assemble a MAC source string; all field values from the format tables are prefixed with the decimal field length in ASCII and concatenated in a specified order. If the field is not present, the '-' character is added to the message in its place. + +**Authorization Request message example:** MAC source string will contain the following field values - AMOUNT, CURRENCY, TERMINAL, TRTYPE, TIMESTAMP, NONCE, MERCH\_URL. + +Suppose that we have a transaction with following fields:: + +| Fields | Size | Description | +| --- | --- | --- | +| AMOUNT | 5 | 11.48 | +| CURRENCY | 3 | USD | +| TERMINAL | 8 | 99999999 | +| TRTYPE | 1 | 1 | +| TIMESTAMP | 14 | 20030105153021 | +| NONCE | 16 | F2B2DD7E603A7ADA | +| MERCH\_URL | 22 | www.sample.com | + +Calculated fields for generate P\_SIGN beow. First of all need to use hex2bin(P\_SIGN) function then verify data using AZERICARDpublic.pem. File will be provided during the test. During the P\_SIGN verification if some parameter will be empty need to add -(dash) parameter instead of value and length of parameter should not count. + +`5`11.48`3`USD`8`99999999`1`1`14`20030105153021`16`F2B2DD7E603A7ADA`14`www.sample.com + +**Verify Callback P\_SIGN parameter:**MAC source string will contain the following field values - AMOUNT, TERMINAL, APPROVAL, RRN, INT\_REF. + +| Fields | Size | Description | +| --- | --- | --- | +| AMOUNT | 5 | 11.48 | +| TERMINAL | 8 | 99999999 | +| APROVAL | 6 | 168975 | +| RRN | 12 | 306276834930 | +| INT\_REF | 16 | 4A29E93C607E33DC | + +Calculated fields for generate P\_SIGN + +`5`11.48`8`99999999`6`168975`12`306276834930`16`4A29E93C607E33DC + +After the MAC source string is assembled, the merchant system must apply a cryptographic algorithm to generate the message authentication code. Gateway supports various cryptographic algorithms and the system administrator may specify which algorithm will be used for a particular merchant terminal. The merchantsystem mustimplement SHA256 sign, add MAC source to sign and crypts with private key in hexadecimal. Merchantsystem implemented by special algorithm fully responsible for the secure storage and usage of corresponding cryptographic keys. An effective key length must be at least 2048 bits for RSA algorithm. MAC field value can be either an upper case or lowercase hexadecimal string. Additional options may be available on demand. + +## 10 Applepay/Googlepay direct integration + +Google və Apple ilə merchantın birbaşa inteqrasiyası üçün linklər aşağıda qeyd edilib. + +- Google Pay: [https://developers.google.com/pay/api/](https://developers.google.com/pay/api/) +- Apple Pay: [https://developer.apple.com/documentation/passkit/apple-pay](https://developer.apple.com/documentation/passkit/apple-pay) or light version + [https://docs.payengine.co/developer-docs/processing-payments/apple-pay/apple-pay-in-your-native-app](https://docs.payengine.co/developer-docs/processing-payments/apple-pay/apple-pay-in-your-native-app) + +#### Applepay/Googlepay Authorization Request Format + +HTTP POST request should be sent to Azericard e-commerce gateway URL: [https://testmpi.3dsecure.az/cgi-bin/cgi\_link](https://testmpi.3dsecure.az/cgi-bin/cgi_link) + +#### Authorization Request Example: + +| Fields | Size | Description | +| --- | --- | --- | +| AMOUNT | 1-12 | Order total amount Required Float with decimal point separator | +| CURRENCY | 3 | Order currency Required Alphabetic, \[A-Z\] | +| ORDER | 6-20 | Merchant order ID Required Integer Last 6 digits used as system trace audit number and must be unique within a day for the terminal ID | +| DESC | 1-50 | This document describes the ApplePay & GPay Acquiring service details and the integration procedure between the Azericard Apple/GPay service and the merchants or banks’ mobile applications. | +| MERCH\_NAME | 1-50 | Merchant name (recognizable by cardholder) | +| MERCH\_URL | 1-250 | Merchant primary website URL Required | +| TERMINAL | 8 | Merchant terminal ID assigned by bank Required | +| TRTYPE | 1 | Must be equal to "1" (Authorization).Transaction type = 0 (Pre-Authorization),Transaction type = 1 (Authorization) | +| COUNTRY | 02 | Merchant country code Conditional Required if merchant server is located in a different time zone rather than the gateway’s server. | +| MERCHANT\_GMT | 1-5 | Merchant’s UTC/GMT time zone offset Conditional Example: -4 Required if merchant is located in different time zone rather than the gateway server. | +| TIMESTAMP | 14 | Merchant transaction timestamp in GMT (GMT time zone offset 0) Required Integer, YYYYMMDDHHMMSS Discrepancy between merchant and gateway servers should not exceed 1 hour, otherwise, the transaction will be declined. | +| NONCE | 1-64 | Merchant nonce Conditional Hexadecimal, 8-32 unpredictable random bytes Required if MAC is used | +| BACKREF | 1-250 | Merchant URL for posting authorization result. | +| P\_SIGN | 1-256 | Merchant MAC Required Hexadecimal | +| CARD | 9-19 | Card number (Primary account number). | +| EXP | 02 | Card expiration month (Numeric 2 digit value). | +| EXP\_YEAR | 02 | Card expiration year (Numeric 2 digit value: 20XX) | +| CVC2\_RC | 1 | CVC2 reason code. values: +value="1" -CVC2 is present +value="0" -CVC2 is not provided +value="2"-CVC2 is illegible | +| EXT\_MPI\_ECI | 02 | Response ECI variable from GooglePay \\ApplePay server1 | +| TAVV | | Response CAVV variable from GooglePay \\ApplePay server | + +**Note1:**For Mastercard card static value ‘02’. + +#### Authorization Response from our system in XML format + +| Fields | Size | Description | +| --- | --- | --- | +| TERMINAL | 8 | Echo from the request | +| TRTYPE | 2 | Echo from the request | +| ORDER | 6-20 | Echo from the request | +| AMOUNT | 1-12 | Amount authorized. Usually, will be equal to original amount plus aquirer’s fee. | +| CURRENCY | 3 | Echo from the request | +| ACTION | 1 | Е-Gateway action code: +0 – Transaction successfully completed; +1 – Duplicate transaction detected; +2 – Transaction declined; +3 – Transaction processing fault. | +| RC | 2 | Transaction response code (ISO-8583 Field 39) | +| APPROVAL | 6 | Client bank’s approval code (ISO-8583 Field 38). Can be empty if not provided by card management system. | +| RRN | 12 | Merchant bank’s retrieval reference number (ISO-8583 Field 37). | +| INT\_REF | 1-32 | E-Commerce gateway internal reference number | +| TIMESTAMP | 14 | E-Commerce gateway timestamp in GMT: YYYYMMDDHHMMSS | +| NONCE | 1-64 | E-Commerce gateway nonce value. Will be filled with 8-32 unpredictable random bytes in hexadecimal format. Will be present if MAC is used. | +| P\_SIGN | 1-256 | E-Commerce gateway MAC (Message Authentication Code) in hexadecimal form. Will be present if MAC is used. | + +#### Merchant MAC – Message Authentication Code + +To authenticate transaction messages on gateway to/from the merchant link, the merchant system should be able to calculate and verify message authentication codes for at least the transactions passed through cardholder browser redirects. Messages that are sent directly to e-Commerce Gateway (“Sales completion” and “Reversal”) may be mutually authenticated with SSL client/server certificates and does not require MAC; if they are not mutually authenticated, MAC for these messages is mandatory. + +MAC is calculated over all fields generated by the merchant system as defined in corresponding format tables (visible and hidden fields generated by the merchant system) except the MAC field (“P\_SIGN”) itself. + +In order to generate or verify the message authentication field, the merchant system must assemble a MAC source string; all field values from the format tables are prefixed with the decimal field length in ASCII and concatenated in a specified order. If the field is not present, the '-' character is added to the message in its place. + +**Authorization Request message example (for TRTYPE=1 and TRTYPE=0):** MAC source string will contain the following field values - AMOUNT, CURRENCY, TERMINAL, TRTYPE, TIMESTAMP, NONCE, MERCH\_URL. + +Suppose that we have a transaction with following fields:: + +| Fields | Size | Description | +| --- | --- | --- | +| AMOUNT | 5 | 11.48 | +| CURRENCY | 3 | USD | +| TERMINAL | 8 | 99999999 | +| TRTYPE | 1 | 1 | +| TIMESTAMP | 14 | 20030105153021 | +| NONCE | 16 | F2B2DD7E603A7ADA | +| MERCH\_URL | 22 | www.sample.com | + +Calculated fields for generate P\_SIGN + +`5`11.48`3`USD`8`99999999`1`1`14`20030105153021`16`F2B2DD7E603A7ADA`14`www.sample.com + +**Verify Callback P\_SIGN parameter:**MAC source string will contain the following field values - AMOUNT, TERMINAL, APPROVAL, RRN, INT\_REF. + +| Fields | Size | Description | +| --- | --- | --- | +| AMOUNT | 5 | 11.48 | +| TERMINAL | 8 | 99999999 | +| APROVAL | 6 | 168975 | +| RRN | 12 | 306276834930 | +| INT\_REF | 16 | 4A29E93C607E33DC | + +Calculated fields for generate P\_SIGN beow. First of all need to use hex2bin(P\_SIGN) function then verify data using AZERICARDpublic.pem. File will be provided during the test. During the P\_SIGN verification if some parameter will be empty need to add -(dash) parameter instead of value and length of parameter should not count. + +`5`11.48`8`99999999`6`168975`12`306276834930`16`4A29E93C607E33DC + +After the MAC source string is assembled, the merchant system must apply a cryptographic algorithm to generate the message authentication code. Gateway supports various cryptographic algorithms and the system administrator may specify which algorithm will be used for a particular merchant terminal. The merchantsystem mustimplement SHA256 sign, add MAC source to sign and crypts with private key in hexadecimal. Merchantsystem implemented by special algorithm fully responsible for the secure storage and usage of corresponding cryptographic keys. An effective key length must be at least 2048 bits for RSA algorithm. MAC field value can be either an upper case or lowercase hexadecimal string. Additional options may be available on demand. + +## 11 Money transfer integration + +This document describes the rules for generating requests sent from merchant payment center to the banks payment center + +The interaction between payment center and bank is carried out according to the HTTP protocol using the Redirect form and JSON format, encoding UTF-8 + +### 11.1 Redirect with parameters + +Redirect with parameters to “Azericard” page URL: + +https://testmt.azericard.com/payment/view + +#### 11.1.1 Description + +You redirect the user to our page with the fields listed below. Then the user enters his card number and other optional parameters on the Azericard page. After this if you get a success response from Azericard so now transaction status is “pending”. + +#### 11.1.2 Request Structure + +| Fields | Size | Description | +| --- | --- | --- | +| Merchant | 1-16 | Company name | +| SRN | 10 | Unique transaction number on your side | +| Amount | 1-2 | Payment amount | +| Cur | 3 | Payment currency | +| ReceiverCredentials | 151 | User full name | +| RedirectLink | 12 | The link to which you want to redirect the client at the end of **the operation** | +| Signature | 32 | Calculated value +MD5(All fields concatenated + Key\*) | + +\* Key will be given to you during the integration + +#### 11.1.3 Card Data Entry + +User enters the card number on the Azericard web page and receives all the required data. + +\- The user will be redirected by clicking "back" button or after 60 seconds + +#### 11.1.4 Redirect Response Structure + +The user will be redirected to the merchant link with the parameters listed below. + +| Fields | Size | Description | +| --- | --- | --- | +| OperationID | 16-20 | Unique operation number on our side | +| SRN | 10 | Unique transaction number on your side | +| Amount | 1-2 | Amount from request | +| Cur | 3 | Currency from request, must be 944 only | +| CardStatus | | User card status on Azericard side | +| ReceiverPAN | 16 | Masked card number | +| Status | | Current transaction status (f.e. “pending”) | +| Timestamp | | Response timestamp | +| Response Code | | Processing response code | +| Message | | Response message | +| Signature | 32 | Calculated value MD5(All fields concatenated + Key) | + +#### 11.1.5 Card status List + +1\. “our\_active” - the card is in our PC and has an active status + +2\. “our\_inactive” - the card is in our PC and has an inactive status (blocked/ expired and etc.) + +3\. “foreign” - the card is not in our PC + +### 11.2 Direct Money Withdrawal Request * + +**Note:** for direct request need PCI DSS certificate + +### 11.1 Description + +The method registers the withdrawal request directly without involving the UI part of the application. + +### 11.2 Request Structure + +POST + +https://testmt.azericard.com/api/direct + +Body + +`{ "ReceiverPAN":"4444444444444444", "SRN":"4142398967", "Amount":"10.00", "Merchant":"TEST", "Cur":"944", "ReceiverCredentials":"Elvin Goderman", "RedirectLink":"http://localhost:8080/payment/callback", "Signature":"4E34786EB5788E4AE2BEF724E2D33E12" }` + +To calculate signatures, concatenate all request fields' values, add the key at the end of the string and calculate MD5 hash of the final string. The example for the Direct Money Withdrawal Request string to be hashed is “44444444444444441414239896710.00TEST944Elvin Godermanhttp://localhost:8080/payment/callback+yourkey” Note that the field order should be the same as the order of fields in the request json body. + +### 11.3 Responses Structure + +#### 11.3.1 Success + +Body: + +`{ "OperationID": "20230414155833291728", "SRN": "4142398967", "Amount": 10.00, "Cur": 944, "CardStatus": "Our_Active", "ReceiverPAN": "476019******7181", "Status": "Pending", "Timestamp": "20230414155835106", "ResponseCode": "0", "Message": "Success", "Signature": "4E34786EB5788E4AE2BEF724E2D33E12" }` + +#### 11.3.2 Error + +Body (Card error): + +`{ "OperationID": "0", "SRN": "4705316214", "Amount": 10.00, "Cur": 944, "CardStatus": "Unknown", "Status": "PAN Value is not valid", "Timestamp": "20230414161509967", "ResponseCode": "137", "Message": "Error", "Signature": "B674CD6EC279C3AA2B4E421AB158F1CB" }` + +#### 11.3.3 Card status List + +1\. “our\_active” - the card is in our PC and has an active status + +2\. “our\_inactive” - the card is in our PC and has an inactive status (blocked/ expired and etc.) + +3\. “foreign” - the card is not in our PC + +4\. “Unknown” - authentication of the card did not start + +#### 11.3.4 Possible Error List + +Codes and messages + +| Response Code | Message | Description | +| --- | --- | --- | +| 0 | Successfully completed | Successfully completed | +| 106 | Signature Error | Input data does not match signature | +| 112 | Payment not found | The payment not found on back end side | +| 116 | Transaction already started | The transaction already started waiting for completion or check by proceeding to the Status check call. | +| 105 | Duplicate transaction | Transaction is not in Pending status cannot be declined or confirmed. Contact Azericard for more info | +| Different errors code | The transaction was declined due to different reasons on the UFX side. | Different causes | + +### 11.4 Confirmation of Transaction request + +#### 11.4.1 Description + +This method confirms pending transaction + +#### 11.4.2 Request Structure + +POST + +https://testmt.azericard.com/api/confirm + +Body: + +`{ "Merchant":"TEST", "SRN": "1234567890", "Amount":10.00, "Cur": 944, "Timestamp" : "20200703224154887", "Signature" : "098f6bcd4621d373cade4e832627b4f6" }` + +### 11.5 Responses Structure + +#### 11.5.1 Success + +Body: + +`{ "OperationID": "c84cbf53-0dd6-441d-95cb-7be8d22dd690", "SRN": "1234567890", "RRN": "PP3031665341", "Amount": 10.00, "Cur": 944, "ReceiverPAN": "4760********7181", "Status": "Confirmed", "Timestamp": "20230131163601372", "ResponseCode": 0, "Message": "Successfully Completed", "Signature": "A75B75FD1ACCB8C5BD3EAB5C892A2A93" }` + +#### 11.5.2 Error + +Body (Card error): + +`{ "OperationID": "c84cbf53-0dd6-441d-95cb-7be8d22dd690", "SRN": "1234567890", "RRN": "PP3031665341", "Amount": 10.00, "Cur": 944, "ReceiverPAN": "4760********7181", "Status": "Confirmed", "Timestamp": "20230131163601372", "ResponseCode": 0, "Message": "Successfully Completed", "Signature": "A75B75FD1ACCB8C5BD3EAB5C892A2A93" }` + +#### 11.5.3 Possible Error List + +Codes and messages + +| Response Code | Message | Description | +| --- | --- | --- | +| 0 | Successfully completed | Successfully completed | +| 106 | Signature Error | Input data does not match signature | +| 112 | Payment not found | The payment not found on back end side | +| 116 | Transaction already started | The transaction already started waiting for completion or check by proceeding to the Status check call. | +| 105 | Duplicate transaction | Transaction is not in Pending status cannot be declined or confirmed. Contact Azericard for more info | +| Different errors code | The transaction was declined due to different reasons on the UFX side. | Different causes | + +### 11.6 Decline reques + +#### 11.6.1 Description + +The method is used to decline pending transactions. + +#### 11.6.2 Request Structure + +POST + +https://testmt.azericard.com/api/decline + +Header: `Content Type: application/json` + +Body: + +`{ "Merchant": "TEST", "SRN": "1234567890", "Amount": 10.00, "Cur": 944, "Timestamp" : "20200703224154887", "Signature" : "183488e0609297b31e1ef18afb2d3673" }` + +#### 11.6.3 Response Structure + +##### Success + +Body: + +`{ "OperationID": "20230124105429272794", "SRN": "1234567890", "Amount": 10.00, "Cur": 944, "Status": "Declined", "Timestamp": "20230124152435358", "ResponseCode": 0, "Message": "Successfully Completed", "Signature": "83B14022FFF060D44A0DD4357E7F3A73" }` + +##### Error + +Body: + +`{ "OperationID": "20230124105429272794", "SRN": "1234567890", "Timestamp": "20230124154656216", "ResponseCode": 105, "Message": "Duplicate transaction", "Signature": "2C13385948D54A0BC73951AD452869E4" }` + +##### Possible Error List + +| Response Code | Message | Description | +| --- | --- | --- | +| 0 | Successfully completed | Successfully completed | +| 106 | Signature Error | Input data does not match signature | +| 112 | Payment not found | The payment not found on back end side | +| 105 | Duplicate transaction | Transaction is not in Pending status cannot be declined or confirmed. Contact Azericard for more info | + +### 11.7 Status of Transaction Request + +#### 11.7.1 Description + +This method is for checking transaction status on PC Azericard side. + +#### 11.7.2 Request Structure + +POST + +https://testmt.azericard.com/api/status + +Body: + +`{ "Merchant":"TEST", "SRN": "1234567890", "Signature" : "098f6bcd4621d373cade4e832627b4f6" }` + +#### 11.7.3 Response Structure + +##### Success + +Body: + +`{ "Merchant": "TEST", "OperationID": "20230125140012670902", "SRN": "1234567890", "RRN": "PU2334078354", "Amount": 10.00, "Cur": 944, "CardStatus": "Our_Active", "ReceiverPAN": "4127********8698", "Status": "Successfully processed", "Timestamp": "20230126122109741", "TransactionStatus": "0", "Signature": "B1CB778B65B3C6039BCB173A5BCCDFDB" }` + +##### Error + +As an example “Not found Payment” response used + +Body: + +`{ "OperationID": "20230126093557306490", "SRN": "1234567890", "Timestamp": "20230126132719593", "ResponseCode": 104, "Message": "Payment not found", "Signature": "582F507C77F9051C4F15E7B8A844E2AF" }` + +##### Possible Error List + +| Response Code | Message | Description | +| --- | --- | --- | +| 0 | Successfully completed | Successfully completed | +| 106 | Signature Error | Input data does not match signature | +| 104 | Payment not found | The payment not found on back end side | +| 113 | The status is pending, the payment needs to be confirmed to complete transaction | The status is pending, the payment needs to be confirmed to complete transaction | +| 115 | The payment was declined previously | The payment was declined previously | +| 110 | Internal error, report to Azericard | Different Azericard related errors are possible, contact Azericard for additional information. | +| 114 | Report service returned no success for the transaction | Report service returned no success for the transaction | + +### 11.8 Alive structure request + +#### 11.8.1 Request Structure + +GET + +https://testmt.azericard.com/api/alive + +#### 11.8.2 Response Structure + +Body: + +`{ "Version": x.x.x, "ResponseCode": 0, "Message": "Successfully" }` + +### 11.9 Fields description + +Field format designation: + +number - numbers of characters 0–9 + +ans - alphanumeric, numeric and special characters, including space + +| Title | Appointment | Format | Length | Presence | +| --- | --- | --- | --- | --- | +| Amount | Transfer amount in currency which is indicated in the field of Cur. The amount is indicated minimal units | number | Less than 12 | Required | +| Cur | Three-digit currency code of the field. Transfer amount. For AZN 944 | number | 3 | Required | +| ReceiverPAN | Transfer recipient card number | number | Less than 20 | Required | +| ReceiverCredentials | Surname Name Father name of recipient | string | Less than 151 | Required | +| Merchant | Merchant id agreed with the bank | string | Less than 16 | Required | +| OperationID | Unique ID operation, formed by merchant if needed for future use | number | Less than 13 | Optional | +| SRN | Transaction reference number, formed by merchant if needed for future use | number | 12 | Required | +| RRN | Transaction reference number, formed by PC Azericard | number | 12 | Required | +| SenderCountry | Sender country code | number | 3 | Optional | +| SenderCity | Sender city code | string | 13 | Optional | +| SenderAddress | Address of sender | string | 25 | Optional | +| SenderCredentials | Name Surname Father name of sender | string | Less than 151 | Optional | +| Attribute | Contains a chain of optional request fields object | any | | Optional | +| SenderPAN | Card number of Sender | number | Less than 20 | Optional | +| TransactionNumber | Transaction ID, formed by PC Bank. Returned in response to the request | string | 15 | Required | +| ApprovalCode | Returned to the response at the request in case of a successful transfer of amount. (at Code=00) | ans | 6 | Required | +| ResponseCode | Response Code | number | 3 | Required | +| CardStatus | Receiver card status in PC Azericard system | string | Less than 20 | Optional | +| Timestamp | Request/Response timestamp | timestamp | 17 | Required | +| Status | Transaction status in local service databasedatabase | string | Less than 20 | Optional | +| TransactionStatus | Transaction on PC Azericard OWS database | number | 3 | Optional | +| Signature | Calculated value MD5(all fields concatenated + Key) | string | 32 | Required | + +### 11.10 Response Code + +| Code | Message | +| --- | --- | +| 0 | Successfully completed, Successfully processed \*(response message depends of local issuing banks) | +| 1 | Refer to card issue | +| 3 | Invalid merchant | +| 5 | Do not honor | +| 12 | Invalid transaction | +| 57 | Transaction not permitted to card holder | +| 61 | Exceeds withdrawal amount limit | +| 65 | Exceeded withdrawal frequency limit | +| 91 | Network error limit | +| 96 | System malfunction | +| 103 | Validation error | +| 104 | Payment not found | +| 105 | Duplicate transaction | +| 106 | Signature Error | +| 108 | Internal error | +| 110 | Internal error, contact Azericard | +| 113 | The status is pending, the payment needs to be confirmed to complete transaction | +| 114 | Report service returned no success for the transaction | +| 116 | Transaction already started | +| 118 | Error while call to ufx | +| 119 | The timestamp not in range | +| 120 | The timestamp has invalid format | +| 123 | The direct withdrawal request is not allowed for this merchant | +| 131 | Merchant doesn't exist | +| 132 | The SRN value is not 10 characters long | +| 133 | Amount value is not valid | +| 134 | Currency code is not valid | +| 135 | Credentials value is not valid | +| 136 | Call back URI is not valid | +| 137 | PAN Value is not valid | +| 138 | Common validation error, contact Azericard | +| 139 | The SRN value is not unique for the given merchant | +| 201 | The payment was declined previously | +| 202 | The transaction is in progress state | + +## 12 Click to Pay + +### 12.1 Overview + +Click to Pay is an online payment solution based on the EMV® Secure Remote Commerce (SRC) standard.Click to Pay allows customers to use their saved payment credentials during online checkout without manually entering full card details for every purchase.For merchants, Click to Pay can be integrated into an existing checkout flow as an additional payment method. + +### 12.2 Benefits + +- Simplified checkout experience. +- Reduced manual entry of card details. +- Improved customer experience. +- Potential increase in payment conversion. +- Support for tokenized payment credentials. +- Modern payment security mechanisms. + +### 12.3 Prerequisites + +- Click to Pay must be enabled for the Merchant Account. +- A valid MERCHANT\_ID must be available. +- Merchant Backend must be configured. +- Merchant Frontend origin must be available. +- Click to Pay integration must be enabled for the required card network. +- Backend endpoints for Capture Context and payment completion must be implemented. + +Note: Merchant activation and technical configuration may depend on the payment provider, acquirer, and Click to Pay implementation used by the merchant. + +### 12.4 Frontend Integration + +The frontend integration is responsible for: + +- Requesting a Capture Context from Merchant Backend. +- Loading the Click to Pay SDK. +- Initializing the Accept instance. +- Initializing Unified Payments. +- Rendering the Click to Pay Button. +- Receiving the transientToken. +- Sending the transientToken to Merchant Backend. + +#### 12.4.1 HTML Example + +``` + + + + + + + + Click to Pay + + + +

Payment

+

Loading...

+
+

+ + + + + + +``` + +### 12.5 Capture Context + +To initialize the Click to Pay SDK, the frontend must first obtain a Capture Context from the Merchant Backend. + +The Capture Context request may contain: + +- Supported card networks. +- Payment type. +- Customer information. +- Order amount. +- Currency. +- Merchant origin. +- Checkout configuration. + +#### 12.5.1 Configuration Example + +``` + + { + "allowedCardNetworks": [ + "VISA" + ], + "allowedPaymentTypes": [ + "CLICKTOPAY" + ], + "captureMandate": { + "billingType": "NONE", + "requestEmail": true, + "requestPhone": true, + "requestShipping": false, + "showAcceptedNetworkIcons": true + }, + "country": "AZ", + "locale": "en_US", + "orderInformation": { + "amountDetails": { + "currency": "AZN", + "totalAmount": "0.15" + } + }, + "targetOrigins": [ + "https://merchant.example.com" + ] + } + +``` + +#### 12.5.2 Main Parameters + +| Parameter | Description | +| --- | --- | +| allowedCardNetworks | Supported card networks | +| allowedPaymentTypes | Supported payment types | +| captureMandate | Customer information request configuration | +| country | Country code | +| locale | User interface locale | +| orderInformation | Order information | +| amountDetails | Payment amount and currency | +| billTo | Customer information | +| targetOrigins | Allowed frontend origins | + +### 12.6 Merchant Backend API + +The Merchant Backend must provide the following endpoints. + +#### 12.6.1 Create Capture Context + +##### Endpoint: + +``` +POST /click-to-pay/capture-context +``` + +##### Headers: + +``` +Content-Type: application/json +x-merchant-id: YOUR_MERCHANT_ID +``` + +##### Request: + +``` + +{ + "allowedCardNetworks": [ + "VISA" + ], + "allowedPaymentTypes": [ + "CLICKTOPAY" + ], + "captureMandate": { + "billingType": "NONE", + "requestEmail": true, + "requestPhone": true, + "requestShipping": false, + "showAcceptedNetworkIcons": true + }, + "country": "AZ", + "locale": "en_US", + "orderInformation": { + "amountDetails": { + "currency": "AZN", + "totalAmount": "0.15" + } + }, + "targetOrigins": [ + "https://merchant.example.com" + ] +} + +``` + +##### Response: + +``` + +{ + "captureContextJwt": "CAPTURE_CONTEXT_JWT", + "clientLibraryUrl": "CLIENT_LIBRARY_URL", + "sessionId": "SESSION_ID" +} + +``` + +##### Response Parameters + +| Parameter | Description | +| --- | --- | +| captureContextJwt | JWT used to initialize the Click to Pay SDK | +| clientLibraryUrl | URL of the Click to Pay client SDK | +| sessionId | Unique payment session identifier | + +### 12.7 Click to Pay Button + +After receiving the Capture Context, the frontend loads the SDK and initializes the Accept instance. + +``` + +await loadScript(clientLibraryUrl); +acceptInstance = await window.Accept(captureContextJwt); + +``` + +Unified Payments is then initialized: + +``` + +const up = await acceptInstance.unifiedPayments(); + +``` + +The Click to Pay Button is rendered using: + +``` + +const transientToken = await up.show({ containers: { paymentSelection: '#payment-buttons' }, }); + +``` + +The following container must be present on the HTML page: + +``` + +
+ +``` + +After the customer completes the payment selection process, the SDK returns a transientToken. The transientToken must be sent to the Merchant Backend to complete the payment. + +### 12.8 Complete Payment + +Endpoint: + +``` + +POST /click-to-pay/complete-flow + +``` + +Headers: + +``` + +Content-Type: application/json +x-merchant-id: YOUR_MERCHANT_ID + +``` + +Request: + +``` + +{ + "sessionId": "SESSION_ID", + "transientToken": "TRANSIENT_TOKEN" +} + +``` + +Example: + +``` + +await fetch(`${SERVER_URL}/click-to-pay/complete-flow`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'x-merchant-id': MERCHANT_ID + }, + body: JSON.stringify({ sessionId, transientToken }), + }); + +``` + +The Merchant Backend uses sessionId and transientToken to complete the payment operation and return the payment result.: + +### 12.9 Payment Statuses + +| Status | Description | +| --- | --- | +| APPROVED | Payment successfully completed | +| DECLINED | Payment was declined | +| PENDING | Final payment result is not yet available | + +Recommended order status mapping: + +APPROVED => PAID + +DECLINED => PAYMENT\_FAILED + +PENDING => PAYMENT\_PENDING + +The merchant should not consider a payment successful based only on the frontend result. The final payment status must be confirmed by the Merchant Backend or the payment provider. + +### 12.10 Integration Checklist + +- Click to Pay is enabled for the Merchant Account. +- MERCHANT\_ID is configured. +- Merchant Backend is available. +- POST /click-to-pay/capture-context is implemented. +- POST /click-to-pay/complete-flow is implemented. +- Merchant frontend origin is configured in targetOrigins. +- Correct clientLibraryUrl is returned. +- Click to Pay Button is displayed correctly. +- transientToken is received successfully. +- transientToken is sent to the backend. +- Successful payments return APPROVED. +- Declined payments are handled correctly. +- PENDING payments are handled separately. +- Payment status is verified on the backend. +- Secret keys are not exposed in frontend code. +- Sensitive payment data is not stored in application logs. + +### 12.11 References + +- EMVCo Secure Remote Commerce (SRC) +- Click to Pay +- Applicable payment network +- Merchant's PSP / Payment Gateway +- Merchant's Acquirer + +Note: Technical parameters, SDK versions, supported payment networks, API endpoints, and authentication requirements may vary depending on the payment provider and integration model. + +#### Sandbox + +To support merchants who wish to test their integrations we have made a sandbox environment. By using following link you can reach many purposes such as developing, new features, testing patches, identifying and squashing bugs. + +P\_SIGN Check: + +[https://testsite.3dsecure.az/sandbox/p-sign.php](https://testsite.3dsecure.az/sandbox/p-sign.php) + +Link to check payment in the test system + +[https://testsite.3dsecure.az/sandbox/auth.php](https://testsite.3dsecure.az/sandbox/auth.php) + +The link below (checkout-reversal-psign.php) will show how and what values are calculated in the mac section of the request's P\_SIGN data before performing a reversal and checkout. + +[https://testsite.3dsecure.az/sandbox/checkout-reversal-psign.php](https://testsite.3dsecure.az/sandbox/checkout-reversal-psign.php) + +The script (checkout-reversal.php) shown below will allow the client to checkout and reverse transactions through the sandbox. TRTYPE=21 should be used for Checkout, and TRTYPE=22 and TRTYPE=24 should be used for Reversal. + +[https://testsite.3dsecure.az/sandbox/checkout-reversal.php](https://testsite.3dsecure.az/sandbox/checkout-reversal.php) + +The links shown below will be used to calculate P\_SIGN transaction status requests and check the status of the payment. + +[https://testsite.3dsecure.az/sandbox/transaction\_status.php](https://testsite.3dsecure.az/sandbox/transaction_status.php) + +[https://testsite.3dsecure.az/sandbox/transaction\_status\_psign.php](https://testsite.3dsecure.az/sandbox/transaction_status_psign.php) + +#### Sample curl requests + +TRTYPE=0,1 + +``` +curl --location --request POST 'https://testmpi.3dsecure.az/cgi-bin/cgi_link' \--header 'Content-Type: application/x-www-form-urlencoded' \--data-urlencode 'AMOUNT=10' \--data-urlencode 'CURRENCY=AZN' \--data-urlencode 'ORDER=20220628084800' \--data-urlencode 'DESC=test Odenish' \--data-urlencode 'TRTYPE=0' \--data-urlencode 'TIMESTAMP=20220825105200' \--data-urlencode 'NONCE=7fdc0caafb113590' \--data-urlencode 'BACKREF=https//test.com/test/callback' \--data-urlencode 'P_SIGN=2f3ac6adba8af5b38dcab617c59284bb69e5618197c60189f38d3f3727cfa2b533147bde577fb8b45e7b7ecaa80d500f069386013ec52367f93bcb127b31c1fa9843ca776cdca571986a925c1ce9f9ad50c29689ca74890369bbb5bcf86af6dea4 e9dca805b360f47752fe9dfc6b5848dc43f2cd9552fad4309545c6169f625de46963ca0401407f9319294db6e8d27f35f9d1bc48a61811502a391cef230d6f219b01cd1e32ad58c21af6f051c56485b4ae3759a3080f6fc2d6d8dcd5f0bb1b2acd7b2b4dc43b1c9fcdc7794e7272281216edd0742b9d3 fd879004fa9b45662d9b7e7f7c7b278f1808461b31a9572c43ae36df78a6eea54e60f4d1a681edc62' \--data-urlencode 'MERCH_NAME=test' \--data-urlencode 'MERCH_URL=http://test.com' \--data-urlencode 'TERMINAL=77777777' \--data-urlencode 'EMAIL=tsupport@test.com' \--data-urlencode 'COUNTRY=AZ' \--data-urlencode 'MERCH_GMT=+4' \--data-urlencode 'M_INFO=ewoiYnJvd3NlclNjcmVlbkhlaWdodCI6IjE5MjAiLAoiYnJvd3NlclNjcmVlbldpZHRoIjoiMTA4MCIsCiJicm93c2VyVFoiOiIwIiwKIm1vYmlsZVBob25lIiA6eyAiY2MiOiI5OTQiLCAic3Vic2NyaWJlciI6IjU1Nzc3Nzc3Nzc3IiB9Cn0' \--data-urlencode 'NAME=Test Testov' +``` + +HTTP POST + +``` +POST /cgi-bin/cgi_link HTTP/1.1Host: testmpi.3dsecure.azContent-Type: application/x-www-form-urlencodedAMOUNT=10&CURRENCY=AZN&ORDER=20220628084800&DESC=test Odenish&TRTYPE=0&TIMESTAMP=20220825105200&NONCE=7fdc0caafb113590&BACKREF=https//test.com/test/callback&P_SIGN=2f3ac6adba8af5b38dcab617c59284bb69e5618197c60189f38d3f3727cfa2b533147bde577fb8b45e7b7ecaa80d500f069386013ec52367f93bcb127b31c1fa9843ca776cdca571986a925c1ce9f9ad50c29689ca74890369bbb5bcf86af6dea4 e9dca805b360f47752fe9dfc6b5848dc43f2cd9552fad4309545c6169f625de46963ca0401407f9319294db6e8d27f35f9d1bc48a61811502a391cef230d6f219b01cd1e32ad58c21af6f051c56485b4ae3759a3080f6fc2d6d8dcd5f0bb1b2acd7b2b4dc43b1c9fcdc7794e7272281216edd0742b9d3 fd879004fa9b45662d9b7e7f7c7b278f1808461b31a9572c43ae36df78a6eea54e60f4d1a681edc62&MERCH_NAME=test&MERCH_URL=http://test.com&TERMINAL=77777777&EMAIL=tsupport@test.com&COUNTRY=AZ&MERCH_GMT=+4&M_INFO=ewoiYnJvd3NlclNjcmVlbkhlaWdodCI6IjE5MjAiLAoiYnJvd3NlclNjcmVlbldpZHRoIjoiMTA4MCIsCiJicm93c2VyVFoiOiIwIiwKIm1vYmlsZVBob25lIiA6eyAiY2MiOiI5OTQiLCAic3Vic2NyaWJlciI6IjU1Nzc3Nzc3Nzc3IiB9Cn0&NAME=Test Testov +``` + +TRTYPE = 21, 22, 24 (Refund / Reversal / Completion) + +``` +curl --location --request POST 'https://testmpi.3dsecure.az/cgi-bin/cgi_link' \--header 'Content-Type: application/x-www-form-urlencoded' \--data-urlencode 'AMOUNT=5' \--data-urlencode 'CURRENCY=AZN' \--data-urlencode 'ORDER=20210506070034' \--data-urlencode 'RRN=112676199769' \--data-urlencode 'INT_REF=5E3601D7C71745A9' \--data-urlencode 'TERMINAL=77777777' \--data-urlencode 'TRTYPE=21' \--data-urlencode 'TIMESTAMP=20210506070051' \--data-urlencode 'NONCE=2c9434b2aa5bb4af' \--data-urlencode 'P_SIGN=2f3ac6adba8af5b38dcab617c59284bb69e5618197c60189f38d3f3727cfa2b533147bde577fb8b45e7b7ecaa80d500f069386013ec52367f93bcb127b31c1fa9843ca776cdca571986a925c1ce9f9ad50c29689ca74890369bbb5bcf86af6dea4 e9dca805b360f47752fe9dfc6b5848dc43f2cd9552fad4309545c6169f625de46963ca0401407f9319294db6e8d27f35f9d1bc48a61811502a391cef230d6f219b01cd1e32ad58c21af6f051c56485b4ae3759a3080f6fc2d6d8dcd5f0bb1b2acd7b2b4dc43b1c9fcdc7794e7272281216edd0742b9d3 fd879004fa9b45662d9b7e7f7c7b278f1808461b31a9572c43ae36df78a6eea54e60f4d1a681edc62' +``` + +HTTP POST + +``` +HTTP POSTPOST /cgi-bin/cgi_link HTTP/1.1Host: testmpi.3dsecure.azContent-Type: application/x-www-form-urlencodedAMOUNT=5&CURRENCY=AZN&ORDER=20210506070034&RRN=112676199769&INT_REF=5E3601D7C71745A9&TERMINAL=77777777&TRTYPE=21&TIMESTAMP=20210506070051&NONCE=2c9434b2aa5bb4af&P_SIGN=2f3ac6adba8af5b38dcab617c59284bb69e5618197c60189f38d3f3727cfa2b533147bde577fb8b45e7b7ecaa80d500f069386013ec52367f93bcb127b31c1fa9843ca776cdca571986a925c1ce9f9ad50c29689ca74890369bbb5bcf86af6dea4 e9dca805b360f47752fe9dfc6b5848dc43f2cd9552fad4309545c6169f625de46963ca0401407f9319294db6e8d27f35f9d1bc48a61811502a391cef230d6f219b01cd1e32ad58c21af6f051c56485b4ae3759a3080f6fc2d6d8dcd5f0bb1b2acd7b2b4dc43b1c9fcdc7794e7272281216edd0742b9d3 fd879004fa9b45662d9b7e7f7c7b278f1808461b31a9572c43ae36df78a6eea54e60f4d1a681edc62 +``` + +TRTYPE = 90 (Transaction Status Inquiry) + +``` +curl --location --request POST 'https://testmpi.3dsecure.az/cgi-bin/cgi_link' \--header 'Content-Type: application/x-www-form-urlencoded' \--data-urlencode 'TRAN_TRTYPE=1' \--data-urlencode 'ORDER=20210506070034' \--data-urlencode 'TERMINAL=77777777' \--data-urlencode 'TRTYPE=90' \--data-urlencode 'TIMESTAMP=20210506070051' \--data-urlencode 'NONCE=2c9434b2aa5bb4af' \--data-urlencode 'P_SIGN=2f3ac6adba8af5b38dcab617c59284bb69e5618197c60189f38d3f3727cfa2b533147bde577fb8b45e7b7ecaa80d500f069386013ec52367f93bcb127b31c1fa9843ca776cdca571986a925c1ce9f9ad50c29689ca74890369bbb5bcf86af6dea4 e9dca805b360f47752fe9dfc6b5848dc43f2cd9552fad4309545c6169f625de46963ca0401407f9319294db6e8d27f35f9d1bc48a61811502a391cef230d6f219b01cd1e32ad58c21af6f051c56485b4ae3759a3080f6fc2d6d8dcd5f0bb1b2acd7b2b4dc43b1c9fcdc7794e7272281216edd0742b9d3 fd879004fa9b45662d9b7e7f7c7b278f1808461b31a9572c43ae36df78a6eea54e60f4d1a681edc62' +``` + +HTTP POST + +``` +POST /cgi-bin/cgi_link HTTP/1.1Host: testmpi.3dsecure.azContent-Type: application/x-www-form-urlencodedTRAN_TRTYPE=1&ORDER=20210506070034&TERMINAL=77777777&TRTYPE=90&TIMESTAMP=20210506070051&NONCE=2c9434b2aa5bb4af&P_SIGN=2f3ac6adba8af5b38dcab617c59284bb69e5618197c60189f38d3f3727cfa2b533147bde577fb8b45e7b7ecaa80d500f069386013ec52367f93bcb127b31c1fa9843ca776cdca571986a925c1ce9f9ad50c29689ca74890369bbb5bcf86af6dea4 e9dca805b360f47752fe9dfc6b5848dc43f2cd9552fad4309545c6169f625de46963ca0401407f9319294db6e8d27f35f9d1bc48a61811502a391cef230d6f219b01cd1e32ad58c21af6f051c56485b4ae3759a3080f6fc2d6d8dcd5f0bb1b2acd7b2b4dc43b1c9fcdc7794e7272281216edd0742b9d3 fd879004fa9b45662d9b7e7f7c7b278f1808461b31a9572c43ae36df78a6eea54e60f4d1a681edc62 +``` diff --git a/docs/az/docs/integrations/epoint/index.md b/docs/az/docs/integrations/epoint/index.md index d4d5c3a..c4195e8 100644 --- a/docs/az/docs/integrations/epoint/index.md +++ b/docs/az/docs/integrations/epoint/index.md @@ -11,6 +11,34 @@ [Rusca](https://epointbucket.s3.eu-central-1.amazonaws.com/files/instructions/API%20Epoint%20ru.pdf) +## Sürətli başlanğıc { #quickstart } + +Ödəniş yaratmaq, müştərini ödəniş səhifəsinə yönləndirmək və statusu yoxlamaq: + +```python +from integrify.epoint import EPointRequest + +# 1. Ödəniş yaradın +resp = EPointRequest.pay( + amount=10, + currency='AZN', + order_id='order-1', + description='Sifariş #1', +) + +if resp.ok: + # 2. Müştərini EPoint ödəniş səhifəsinə yönləndirin + print(resp.body.redirect_url) + + # 3. Nəticə callback-ə gəlir; istənilən vaxt statusu özünüz də yoxlaya bilərsiniz + status = EPointRequest.get_transaction_status(transaction_id=resp.body.transaction) + print(status.body.status) # new, success, returned, error, server_error +else: + print(resp.body.message) +``` + +Asinxron istifadə üçün `EPointAsyncRequest` import edib, eyni metodları `await` ilə çağırın. + ## Sorğular listi { #list-of-requests } | Sorğu metodu | Məqsəd | EPoint API | Callback-ə sorğu atılır | diff --git a/docs/az/docs/integrations/kapitalbank/index.md b/docs/az/docs/integrations/kapitalbank/index.md index c088e4b..0ceea7f 100644 --- a/docs/az/docs/integrations/kapitalbank/index.md +++ b/docs/az/docs/integrations/kapitalbank/index.md @@ -18,6 +18,33 @@ [AZ, EN, RU](https://pg.kapitalbank.az/docs) +Markdown versiyası (bu saytda): [Kapital Bank E-commerce API](./official/api.md) + +## Sürətli başlanğıc { #quickstart } + +Sifariş yaratmaq, müştərini bankın ödəniş səhifəsinə yönləndirmək və statusu yoxlamaq: + +```python +from integrify.kapitalbank import KapitalRequest + +# 1. Sifariş yaradın +resp = KapitalRequest.create_order(amount=10, currency='AZN', description='Sifariş #1') + +if resp.ok: + order = resp.body.data + + # 2. Müştərini bankın ödəniş səhifəsinə yönləndirin + print(order.redirect_url) + + # 3. Müştəri KAPITAL_REDIRECT_URL-ə qayıtdıqdan sonra statusu yoxlayın + info = KapitalRequest.get_order_information(order_id=order.id) + print(info.body.data.status) # FullyPaid, Declined, Cancelled, ... +else: + print(resp.body.error) +``` + +Asinxron istifadə üçün `KapitalAsyncRequest` import edib, eyni metodları `await` ilə çağırın. + ## Sorğular listi { #list-of-requests } | Sorğu metodu | Məqsəd | Kapital API | Callback-ə sorğu atılır | diff --git a/docs/az/docs/integrations/kapitalbank/official/api.md b/docs/az/docs/integrations/kapitalbank/official/api.md new file mode 100644 index 0000000..d3c9166 --- /dev/null +++ b/docs/az/docs/integrations/kapitalbank/official/api.md @@ -0,0 +1,1046 @@ +# Kapital Bank E-commerce API Sənədləşməsi + +???+ info + Bu səhifə Kapital Bank-ın rəsmi API sənədinin ([pg.kapitalbank.az/docs](https://pg.kapitalbank.az/docs)) Markdown versiyasıdır. Uyğunsuzluq olarsa, orijinal mənbə əsas götürülür. + +## Təsvir + +Bu sənədləşmə Kapital Bank müştəriləri üçün e-ticarət sisteminə inteqrasiya məqsədi ilə nəzərdə tutulmuşdur. + +## Əsas URL + +- Test Mühiti: https://txpgtst.kapitalbank.az/api +- Prod Mühiti: https://e-commerce.kapitalbank.az/api + +## Autentifikasiya + +Bütün əməliyyatlar üçün autentifikasiya məqsədilə BasicAuth formatında başlıq tələb olunur. Bu başlıq tacirin istifadəçi adı və parolunu ehtiva edir və onlar base64 formatında kodlaşdırılır. Bu, tacirin istifadəçi adı və parolunun açıq mətn kimi göndərilməsinin qarşısını alaraq daha təhlükəsiz autentifikasiya üsuludur. + +- BasicAuth haqqında daha çox məlumat: https://www.twilio.com/docs/glossary/what-is-basic-authentication +- PostMan-da BasicAuth https://learning.postman.com/docs/sending-requests/authorization/authorization-types/ +- Java : https://www.baeldung.com/java-httpclient-basic-auth +- ASP.NET : https://code-maze.com/aspnetcore-basic-authentication-with-httpclient/ +- Java : https://www.baeldung.com/java-httpclient-basic-auth +- Php : https://www.gavsblog.com/blog/how-to-use-basic-authentication-with-php-curl +- NodeJS : https://www.geeksforgeeks.org/basic-authentication-in-node-js-using-http-header/ + +## Basic Auth test etimadnamələri + +- İstifadəçi adı: TerminalSys/kapital +- Şifrə: kapital123 + +## Əməliyyat Axını + +## Əməliyyat axını (Adi ödəniş) + +1. Sifariş yaratma sorğusu göndərin (Order_SMS). Əgər cavab müsbətdirsə, 2-ci addıma keçin. +2. Sifariş yaratma cavabından alınan məlumatlarla URL-ə yönləndirin (1-ci bənd): URL nümunəsi{{order.hppUrl}}/flex?id={{order.id}}&password={{order.password}} +3. PC-də (Emal Mərkəzi tərəfində) əməliyyat tamamlandıqdan sonra müştərini bir neçə (aşağıda göstərilən) əməliyyat sahəsi ilə birlikdə yönləndirin (callback) URL-ə yönləndirin. Əməliyyat axını tamamlandı. Callback URL nümunəsi: {{callback.url}}?ID=1234&STATUS=FullyPaidSTATUS parametri dəyəri müvəqqəti ola bilər. Buna görə də əməliyyatın statusunu əməliyyat detalları sorğusu ilə təsdiqləməlisiniz. + +## Preauthorization əməliyyat axını (Preauthorization + Clearing) + +1. Sifariş yaratma sorğusu göndərin (Order_DMS). Əgər cavab müsbətdirsə, 2-ci addıma keçin. +2. Sifariş yaratma cavabından alınan məlumatlarla URL-ə yönləndirin (1-ci bənd): URL nümunəsi{{order.hppUrl}}/flex?id={{order.id}}&password={{order.password}} +3. PC-də (Emal Mərkəzi tərəfində) əməliyyat tamamlandıqdan sonra müştərini bir neçə (aşağıda göstərilən) əməliyyat sahəsi ilə birlikdə yönləndirin (callback) URL-ə yönləndirin. Preauthorization birinci mərhələ tamamlandı və məbləğ blokda olacaq. +4. Xidmət və ya məhsul təmin edildikdən sonra İcra Əməliyyatı Clearing sorğusu göndərməlisiniz (preauthorization əməliyyatının ikinci addımı). Əməliyyat axını tamamlandı. + +## Təkrar ödəniş axını (cvv2 və 3d yoxlamaları olmadan) + +1. Təkrar ödəniş sifarişini yaratma sorğusu göndərin (Recurring). Əgər cavab müsbətdirsə, 2-ci addıma keçin. +2. Mənbə Token təyin etmə sorğusu göndərin. Əgər cavab müsbətdirsə, 3-cü addıma keçin. +3. Əməliyyatı icra edin (Saxlanılan kart ilə alış). Əgər cavab müsbətdirsə, əməliyyat tamamlandı. + +## Sifariş Kredit Əməliyyatı axını (Karta vəsait göndərmək) + +1. Təkrar ödəniş sifarişini yaratma sorğusu göndərin (Sifariş Kredit Əməliyyatı). Əgər cavab müsbətdirsə, 2-ci addıma keçin. +2. Mənbə Token təyin etmə sorğusu göndərin. Əgər cavab müsbətdirsə, 3-cü addıma keçin. +3. Əməliyyatı icra etmə sorğusu göndərin (Kredit Əməliyyatını İcra Et). Əgər cavab müsbətdirsə, əməliyyat tamamlandı. + +## Test kart məlumatları + +- PAN: 4169741330151778 +- ExpDate: 06/25 +- CVV: 119 + +- PAN: 5239151747183468 +- ExpDate: 11/24 +- CVV2: 292 + +## Sifariş Yarat + +Bu endpoint yeni sifariş yaratmağa imkan verir. + +### URI + +POST /order + +### Sorğu + +- typeRid: Sifarişin növü. Sifariş növlərinin siyahısı: + - Order_SMS: Alış əməliyyatları üçün + - Order_DMS: Preauthorization əməliyyatları üçün + - Order_REC: Təkrar Alış əməliyyatları üçün (saxlanılan kart ilə əməliyyatlar) + - DMSN3D: Təkrar Preauthorization əməliyyatları üçün (saxlanılan kart ilə əməliyyatlar) + - OCT: Kartdan Karta əməliyyatlar üçün (Sifariş Kredit Əməliyyatı) +- amount: Sifarişə aid məbləğ. +- currency: Sifarişin valyutası. +- language: Sifariş üçün dil üstünlüyü. +- description: Sifariş haqqında qısa təsvir və ya şərh. + - Taksit əməliyyatları üçün təsvir sahəsinə ayları bu formatda göndərməlisiniz: TAKSIT=6 +- hppRedirectUrl: Əməliyyatı tamamladıqdan sonra yönləndiriləcək URL. +- hppCofCapturePurposes: Sifariş üçün Ödəniş səhifəsində Kart-on-File (COF) saxlama məqsədini əhatə edən massiv. Saxlayarkən bütün 3 məlumatı istifadə edin. +- aut: hppCofCapturePurpose ilə birlikdə istifadə olunur. Bu parametr təyin edildikdə, ödəniş səhifəsində kart saxlama üçün seçmə qutusu həmişə aktiv olacaq. +- srcToken.storedId: Bu parametr ödəniş tokenini (Saxlanılan Kart) yaratmaq üçün istifadə olunur. + +### Cavab + +- id: Sifariş üçün unikal identifikator. +- hppUrl: Sifariş ilə əlaqəli Hosted Payment Page (HPP) URL-i. +- password: Sifariş ilə əlaqəli parol və ya autentifikasiya tokeni. +- status: Sifarişin cari statusu, "Preparing" və ya başqa status ola bilər. +- cvv2AuthStatus: Sifariş üçün CVV2 autentifikasiya tələbi. +- secret: Sifariş ilə əlaqəli gizli və ya əlavə təhlükəsizlik məlumatı. + +### Nümunə + +Sorğu + +``` +{ + "order": { + "typeRid":"Order_SMS", + "amount":"1", + "currency":"AZN", + "language": "az", + "title": "Othub", + "description": "Testdesc", + "initiationEnvKind":"Browser", + "hppRedirectUrl":"http://txpgtst.kapitalbank.az", + "hppCofCapturePurposes": [ + "UnspecifiedMit", + "Cit", + "Recurring" + ], + "aut":{ + "purpose": "AddCard" + }, + "srcToken": { + "storedId": 1234 + } + } +} +``` + +Sadə ödəniş sorğusu: + +``` +{ + "order": { + "typeRid":"Order_SMS", + "amount":"1", + "currency":"AZN", + "language": "az", + "title": "Othub", + "description": "Testdesc", + "hppRedirectUrl":"http://txpgtst.kapitalbank.az" + } +} +``` + +Sadə preauthorization sorğusu: + +``` +{ + "order": { + "typeRid":"Order_DMS", + "amount":"1", + "currency":"AZN", + "language": "az", + "title": "Othub", + "description": "Testdesc", + "hppRedirectUrl":"http://txpgtst.kapitalbank.az" + } +} +``` + +Account-to-Card (OCT - Sifariş Kredit Əməliyyatı): + +``` + + { + "order": { + "typeRid":"OCT", + "amount":"1", + "currency":"AZN", + "language": "az", + "title": "Othub", + "description": "Testdesc" + } +} +``` + +Installment (Taksit) sorğusu: + +``` +{ + "order": { + "typeRid":"Order_SMS", + "amount":"1.0", + "currency":"AZN", + "language": "az", + "description": "TAKSIT=3", + "hppRedirectUrl":"http://txpgtst.kapitalbank.az" + } +} +``` + +Cavab + +``` +{ + "order": { + "id": 4595, + "hppUrl": "https://txpgtst.kapitalbank.az/flex", + "password": "8xjpd1ejxdma", + "status": "Preparing", + "cvv2AuthStatus": "Required", + "secret": "312866" + } +} +``` + +## Mənbə Tokeni Təyin Et + +Bu sorğu ödəniş tokeni yaratmaq üçün istifadə olunur. + +### URI + +POST /order/{ID}/set-src-token?password={{orderPassword}} + +### Saxlanılan ID ilə + +### Sorğu + +- order.initiationEnvKind Sifarişin başlanğıc mühit növünü göstərir, "Server" olaraq göstərilir (MIT/Təkrar əməliyyatlar üçün) və "Browser" (CIT əməliyyatları üçün). +- token.storedId: Saxlanılan kartın identifikatoru. + +### Nümunə + +Sorğu + +``` +{ + "order":{ + "initiationEnvKind":"Server" + }, + "token": { + "storedId": 5125 + } +} +``` + +Cavab + +``` +{ + "order": { + "status": "Preparing", + "cvv2AuthStatus": "IneligibleOrder", + "tdsV1AuthStatus": "IneligibleOrder", + "tdsV2AuthStatus": "IneligibleOrder", + "otpAutStatus": "IneligibleOrder", + "srcToken": { + "id": 6298, + "paymentMethod": "Card", + "role": "Src", + "status": "Active", + "regTime": "2024-08-09 15:03:26", + "displayName": "416974******1778", + "card": { + "expiration": "1125", + "brand": "Visa" + } + } + } +} +``` + +## Təyinat Tokeni Təyin Et + +Bu sorğu Kart Köçürmə axınında təyinat kartını təyin etmək üçün istifadə olunur. + +### URI + +POST /order/{ID}/set-dst-token?password={{orderPassword}} + +### Sorğu + +- token.card.panBlock.data: Kart Pan. + +### Nümunə + +Sorğu + +``` +{ + "token": { + "card": { + "panBlock": { + "data": "4169741330151778" + }, + "entryMode": "ECommerce" + } + } +} +``` + +Cavab + +``` +{ + "order": { + "status": "Preparing", + "cvv2AuthStatus": "IneligibleOrder", + "tdsV1AuthStatus": "IneligibleOrder", + "tdsV2AuthStatus": "IneligibleOrder", + "otpAutStatus": "IneligibleOrder", + "srcToken": { + "id": 6298, + "paymentMethod": "Card", + "role": "Src", + "status": "Active", + "regTime": "2024-08-09 15:03:26", + "displayName": "416974******1778", + "card": { + "expiration": "1125", + "brand": "Visa" + } + } + } +} +``` + +## Əməliyyatın İcrası + +Bu sorğu əməliyyatı yekunlaşdırmaq üçün istifadə olunur. + +### URI + +POST /order/{ID}/exec-tran + +### Sorğu + +- phase Əməliyyat mərhələsinin göstəricisi. Mərhələ nümunələri: + - Single. Bir addımlı əməliyyatlar üçün (Standart Alış) + - Auth. Preauthorization əməliyyatının ilk mərhələsi üçün. authorizationKind ilə birlikdə istifadə olunmalıdır. + - Clearing. Preauthorization əməliyyatının ikinci mərhələsi üçün. +- type Əməliyyatın növü. Növ nümunələri: + - Credit. Kartdan Karta əməliyyat üçün. + - Refund. Əməliyyatdan pulu geri qaytarmaq üçün. +- amount Əməliyyat üçün təsdiqlənəcək məbləğ. Əgər göstərilməyibsə, məbləğ Sifariş Yaratma Sorğusundakı məbləğdən istifadə ediləcək. +- authorizationKind Preauthorization əməliyyatında Auth mərhələsi ilə birlikdə istifadə olunmalıdır. + +conditions.cofUsage Təkrar əməliyyat göstəricisi. + +``` +{ + "tran":{ + "phase":"Auth", + "type":"Credit", + "amount":"1.00", + "authorizationKind": "Preliminary", + "conditions":{ + "cofUsage":"Recurring" + } + } +} +``` + +### Nümunə + +#### Sorğu + +Clearing (Preauthorization əməliyyatının ikinci mərhələsi): + +``` +{ + "tran":{ + "phase":"Clearing", + "amount":"1.00" + } +} +``` + +Saxlanılan kart ilə əməliyyat: + +``` + + { + "tran":{ + "phase":"Single", + "conditions":{ + "cofUsage":"Recurring" + } + } +} +``` + +Saxlanılan kart ilə Preauthorization əməliyyat: + +``` +{ + "tran":{ + "phase":"Auth", + "authorizationKind": "Preliminary", + "conditions":{ + "cofUsage":"Recurring" + } + } +} +``` + +Account-to-Card (OCT) + +``` +{ + "tran":{ + "phase":"Single", + "type":"Credit" + } +} +``` + +### Cavab + +Uğurlu cavab + +``` +{ + "tran": { + "approvalCode": "053703", + "match": { + "tranActionId": "240422-13060545-000oed=", + "ridByPmo": "17302955" + }, + "pmoResultCode": "1" + } +} +``` + +Səhv ilə olan Cavab + +``` +{ + "errorCode": "PmoDecline", + "errorDescription": "Transaction declined by PMO: Auth Response: 52 - Card not found for MBR calculation. PAN=416974******1778, ExpDate from Track2 (YYMM)=2511", + "errorDetails": { + "declineReason": "SrcCardInvalid", + "match": { + "ridByPmo": "17947770" + }, + "pmoResultCode": "52", + "pmoDeclineDesc": "Card not found for MBR calculation. PAN=416974******1778, ExpDate from Track2 (YYMM)=2511" + } +} +``` + +## Geri Ödəniş (Refund) + +Bu əməliyyat pulu əməliyyat üçün geri qaytarmaq məqsədilə istifadə olunur. Sorğu nümunəsi, İcra Əməliyyatı (Execute Transaction) sorğusu ilə eyni və eyni URI-dır. + +``` +{ + "tran":{ + "phase":"Single", + "amount":"2.00", + "type": "Refund" + } +} +``` + +## Ləğv Etmə (Reversal) + +Bu sorğu gün ərzində əməliyyatı ləğv etmək üçün istifadə olunur. + +### URI + +POST /order/{ID}/exec-tran + +### Sorğu + +Sorğu, İcra Əməliyyatı (Execute Transaction) sorğusu ilə eynidir, lakin fərqli parametrlərlə. + +- phase Əməliyyat mərhələsinin göstəricisi. Mərhələ nümunələri: + - Single. Bir addımlı əməliyyatlar üçün (Standart Alış) + - Auth. Preauthorization əməliyyatının ilk mərhələsi üçün. authorizationKind ilə birlikdə istifadə olunmalıdır. + - Clearing. Preauthorization əməliyyatının ikinci mərhələsi üçün. +- voidKind Ləğv Etmə əməliyyatının göstəricisi. Ləğv növləri: + - Full. Əməliyyatın tam məbləğini geri qaytarmaq üçün istifadə olunur. + - Partial. Əvvəlki məbləğdən az olan vəsaitləri geri qaytarmaq üçün istifadə olunur. Bir dəfə istifadə oluna bilər. + +amount Əməliyyat üçün geri qaytarılacaq məbləğ. Yalnız qismən geri qaytarma istifadə edildikdə göstərilməlidir. + +``` +{ + "tran":{ + "phase":"Single", + "amount":"1.00", + "voidKind": "Partial" + } +} +``` + +### Nümunə + +#### Sorğu + +Alışdan sonra tam ləğv etmə + +``` +{ + "tran":{ + "phase":"Single", + "voidKind": "Full" + } +} +``` + +Alışdan sonra hissəli ləğv etmə + +``` + + { + "tran":{ + "phase":"Single", + "amount":"1.00", + "voidKind": "Partial" + } +} +``` + +Preauthorization sorğusunnan sonra tam ləğv etmə (Birinci mərhələdən sonra) + +``` +{ + "tran":{ + "phase":"Auth", + "voidKind": "Full" + } +} +``` + +Preauthorization sorğusunnan sonra tam ləğv etmə (İkinci mərhələdən sonra) + +``` +{ + "tran":{ + "phase":"Clearing", + "voidKind": "Full" + } +} +``` + +## Sifariş Təfərrüatlarını Al (Get Order Details) + +Bu sorğu əməliyyat haqqında məlumat almaq üçün istifadə olunur. + +### URI + +GET /order/{ID} + +### Sorğu + +Əlavə məlumat almaq üçün URI-ə parametrlər əlavə edə bilərsiniz. + +### PARAMETRLƏR + +- tranDetailLevel=2 : Bu parametr əməliyyat haqqında bütün məlumatları əlavə edir. +- tokenDetailLevel=2 : Bu parametr ödəniş tokeni və ya kart haqqında bütün məlumatları əlavə edir. +- orderDetailLevel=2 : Bu parametr sifariş haqqında bütün məlumatları əlavə edir. + +### Nümunə + +Sorğu + +https://txpgtst.kapitalbank.az/api/order/1111/?&tranDetailLevel=2&tokenDetailLevel=2&orderDetailLevel=2 + +Cavab + +Parametrsiz sadə cavab + +``` +{ + "order": { + "id": 5531, + "typeRid": "Order_SMS", + "status": "Refunded", + "prevStatus": "FullyPaid", + "lastStatusLogin": "E1010", + "amount": 1, + "currency": "AZN", + "createTime": "2024-06-12 15:38:23", + "finishTime": "2024-06-12 15:39:17", + "title": "Othub", + "type": { + "title": "Single message" + } + } + } +``` + +Detallı cavab bütün parametrlərlə + +``` +{ + "order": { + "id": 5531, + "hppUrl": "https://txpgtst.kapitalbank.az/flex", + "hppRedirectUrl": "http://txpgtst.kapitalbank.az", + "password": "1a06f5aj3yhqr", + "status": "Refunded", + "prevStatus": "FullyPaid", + "lastStatusLogin": "E1010", + "amount": 1, + "currency": "AZN", + "terminal": { + "id": 41, + "rid": "E1000010", + "title": "E1000010", + "mcc": 3011, + "status": "Active" + }, + "srcAmount": 1, + "srcAmountFull": 1, + "srcCurrency": "AZN", + "dstAmount": 1, + "dstCurrency": "AZN", + "createTime": "2024-06-12 15:38:23", + "finishTime": "2024-06-12 15:39:17", + "trans": [ + { + "approvalCode": "047347", + "actionId": "240612-11385786-000tn5=", + "orderId": 5531, + "terminalId": 41, + "merchantId": 101, + "billingStatus": "Normal", + "isReversal": false, + "ridByAcquirer": "17579346", + "ridByPmo": "17579346", + "regTime": "2024-06-12 15:38:57", + "clearAmount": 1, + "clearCcy": "AZN", + "amount": 1, + "currency": "AZN", + "description": "Purchase", + "phase": "Single", + "type": "Purchase", + "pmoResultCode": "1" + }, + { + "approvalCode": "963348", + "actionId": "240612-11391689-000tn7=", + "orderId": 5531, + "terminalId": 41, + "merchantId": 101, + "billingStatus": "Normal", + "isReversal": false, + "ridByAcquirer": "17579348", + "ridByPmo": "17579348", + "regTime": "2024-06-12 15:39:16", + "clearAmount": -1, + "clearCcy": "AZN", + "amount": 1, + "currency": "AZN", + "description": "Refund", + "phase": "Single", + "type": "Refund", + "pmoResultCode": "1" + } + ], + "cvv2AuthStatus": "Provided", + "tdsV1AuthStatus": "IneligibleOrder", + "tdsV2AuthStatus": "Verified", + "tdsServerUrl": "http://172.21.14.67:1341", + "authorizedChargeAmount": 1, + "clearedChargeAmount": 1, + "clearedRefundAmount": 1, + "title": "Othub", + "description": "Testdesc", + "language": "az", + "srcToken": { + "id": 4833, + "paymentMethod": "Card", + "role": "Src", + "status": "Active", + "regTime": "2024-06-12 15:38:28", + "entryMode": "ECommerce", + "displayName": "416974******1778", + "owner": {}, + "card": { + "authentication": { + "needCvv2": false, + "needTds": false, + "tranId": "a3b35fe8-e245-4a3e-ba01-e250a4ac20ad", + "tdsDsTranId": "c087b446-192b-48fb-b78f-2c4bb53ac26c", + "timestamp": "2024-06-12 11:38:23", + "tdsProtocolVer": "2.2.0", + "cryptType": "Tds", + "cryptVal": "AJkBA0KTRAAAAABklEFkdQAAAAA=", + "eci": "05", + "tdsARes": "{"threeDSServerTransID":"a3b35fe8-e245-4a3e-ba01-e250a4ac20ad","acsTransID":"6663aebe-7f7a-4f34-be7f-bdb9731c1adf","dsTransID":"c087b446-192b-48fb-b78f-2c4bb53ac26c","messageType":"ARes","messageVersion":"2.2.0","messageExtension":[{"name":"MesExt2","id":"ID2","criticalityIndicator":false,"data":{"valueOne":"value"}}],"dsReferenceNumber":"DSRefNumVISA","acsReferenceNumber":"3DS_LOA_ACS_COPL_020100_00081","acsOperatorID":"ACS-V210-KAPITAL-BANK-78858","authenticationValue":"AJ************************A=","eci":"05","transStatus":"Y","transStatusReason":"17"}" + }, + "expiration": "1126", + "brand": "Visa", + "issuerRid": "4" + } + }, + "merchant": { + "id": 101, + "rid": "E1000010", + "title": "E1000010", + "businessAddress": { + "country": "AZE", + "countryA2": "AZ", + "countryN3": 31 + }, + "trustConsumerPhone": false + }, + "initiationEnvKind": "Server", + "type": { + "allowVoid": true, + "hppTranPhase": "Single", + "secretLength": 6, + "title": "Single message", + "rid": "Order_SMS", + "paymentMethods": [ + "Card" + ], + "cardBrands": [ + "Visa", + "Mastercard" + ], + "allowTdsAttempt": false, + "allowTdsCant": false, + "allowTdsChallenged": false, + "allowSurcharge": false, + "allowTranTypes": [ + "Purchase", + "Refund", + "CheckToken" + ], + "allowTranPhases": [ + "Single", + "Prepare" + ], + "allowAuthKinds": [ + "Final", + "Undefined" + ], + "allowCofStoreUsages": [ + "Cit", + "PartialShipment", + "Instalment", + "Recurring", + "UnspecifiedMit", + "DelayedCharge" + ], + "orderClass": "Sale", + "allowCVV2": true + }, + "hppCofCapturePurposes": [ + "UnspecifiedMit" + ], + "custAttrs": [], + "reportPubs": {} + } + } +``` + +Detallı cavab saxlanılan kart məlumati ilə bir yerdə (storedTokens.id) + +``` +{ + "order": { + "id": 10947, + "hppUrl": "https://txpgtst.kapitalbank.az/flex", + "hppRedirectUrl": "http://txpgtst.kapitalbank.az", + "password": "mzvjai9qsj8x", + "status": "FullyPaid", + "prevStatus": "Preparing", + "lastStatusLogin": "E1010", + "amount": 5, + "currency": "AZN", + "terminal": { + "id": 41, + "rid": "E1000010", + "title": "E1000010", + "mcc": 3011, + "status": "Active" + }, + "srcAmount": 5, + "srcAmountFull": 5, + "srcCurrency": "AZN", + "dstAmount": 5, + "dstCurrency": "AZN", + "createTime": "2024-07-30 16:57:36", + "storedTokens": [ + { + "id": 5654 + } + ], + "trans": [ + { + "approvalCode": "511369", + "actionId": "240730-12583839-001drl=", + "orderId": 10947, + "terminalId": 41, + "merchantId": 101, + "billingStatus": "Normal", + "isReversal": false, + "ridByAcquirer": "17850012", + "ridByPmo": "17850012", + "regTime": "2024-07-30 16:58:38", + "clearAmount": 5, + "clearCcy": "AZN", + "amount": 5, + "currency": "AZN", + "description": "Purchase", + "phase": "Single", + "type": "Purchase", + "pmoResultCode": "1" + } + ], + "cvv2AuthStatus": "Provided", + "tdsV1AuthStatus": "IneligibleOrder", + "tdsV2AuthStatus": "Verified", + "tdsServerUrl": "http://172.21.14.67:1340", + "authorizedChargeAmount": 5, + "clearedChargeAmount": 5, + "clearedRefundAmount": 0, + "title": "Othub", + "description": "Testdesc", + "language": "az", + "srcToken": { + "id": 5652, + "paymentMethod": "Card", + "role": "Src", + "status": "Active", + "regTime": "2024-07-30 16:57:43", + "entryMode": "ECommerce", + "displayName": "510307******3118", + "owner": {}, + "card": { + "authentication": { + "needCvv2": false, + "needTds": false, + "tranId": "0682c816-a368-4f66-9c27-ea2298b8b2a8", + "tdsDsTranId": "fd1a1d37-1ec8-4d47-a8cd-6f1d640d8425", + "timestamp": "2024-07-30 12:57:36", + "tdsProtocolVer": "2.2.0", + "cryptType": "Tds", + "cryptVal": "xgR6+aR8AAAAAAAAAAAAAAAAAAAA", + "eci": "02", + "tdsARes": "{"threeDSServerTransID":"0682c816-a368-4f66-9c27-ea2298b8b2a8","acsTransID":"ace44ca4-df3d-478d-9553-dd20174169d8","dsTransID":"fd1a1d37-1ec8-4d47-a8cd-6f1d640d8425","messageType":"ARes","messageVersion":"2.2.0","messageExtension":[{"name":"MesExt2","id":"ID2","criticalityIndicator":false,"data":{"valueOne":"value"}}],"dsReferenceNumber":"DSRefNum","acsReferenceNumber":"3DS_LOA_ACS_COPL_020100_00081","acsChallengeMandated":"N","acsOperatorID":"ACS-V210-KAPITAL-BANK-78858","acsURL":"https://acs1test.kapitalbank.az","authenticationType":"02","transStatus":"C"}", + "tdsRReq": "{"threeDSServerTransID":"0682c816-a368-4f66-9c27-ea2298b8b2a8","acsTransID":"ace44ca4-df3d-478d-9553-dd20174169d8","dsTransID":"fd1a1d37-1ec8-4d47-a8cd-6f1d640d8425","messageType":"RReq","messageVersion":"2.2.0","authenticationMethod":"02","authenticationType":"02","authenticationValue":"xg************************AA","eci":"02","interactionCounter":"01","messageCategory":"01","transStatus":"Y"}" + }, + "expiration": "0125", + "brand": "Mastercard", + "issuerRid": "5" + } + }, + "merchant": { + "id": 101, + "rid": "E1000010", + "title": "E1000010", + "businessAddress": { + "country": "AZE", + "countryA2": "AZ", + "countryN3": 31 + }, + "trustConsumerPhone": false + }, + "initiationEnvKind": "Browser", + "type": { + "allowVoid": true, + "hppTranPhase": "Single", + "secretLength": 6, + "title": "Single message", + "rid": "Order_SMS", + "paymentMethods": [ + "Card" + ], + "cardBrands": [ + "Visa", + "Mastercard" + ], + "allowTdsAttempt": false, + "allowTdsCant": false, + "allowTdsChallenged": false, + "allowSurcharge": false, + "allowTranTypes": [ + "Purchase", + "Refund", + "CheckToken" + ], + "allowTranPhases": [ + "Single", + "Prepare" + ], + "allowAuthKinds": [ + "Final", + "Undefined" + ], + "allowCofStoreUsages": [ + "Cit", + "PartialShipment", + "Instalment", + "Recurring", + "UnspecifiedMit", + "DelayedCharge" + ], + "orderClass": "Sale", + "allowCVV2": true + }, + "hppCofCapturePurposes": [ + "UnspecifiedMit", + "Cit", + "Recurring" + ], + "custAttrs": [], + "reportPubs": {} + } + } +``` + +## Google Pay™ İnteqrasiyası + +Əgər siz Google Pay™ vasitəsilə ödənişlərin işlənməsini aktivləşdirmək istəyirsinizsə, zəhmət olmasa, kuratorunuzla əlaqə saxlayın və o, bu funksiyanı sizin əsas girişinizə əlavə edəcək. + +## Google Pay™ üçün məlumatlar + +- gatewayid: ecommercekapitalbank +- gatewayMerchantId: testmerch + +Qeyd: Bu gatewayMerchantId yalnız test mühitində əməliyyatlar aparmaq üçün istifadə olunur. Testlər uğurla keçildikdən sonra sizə istehsalat mühitində istifadə üçün öz gatewayMerchantId təqdim olunacaq. + +#### İnteqrasiya üçün sənəd bağlantıları: + +- Android: [https://developers.google.com/pay/api/android/overview?hl=ru](https://developers.google.com/pay/api/android/overview?hl=ru) +- Web: https://developers.google.com/pay/api/web/overview?hl=ru +- Design Guidline: [https://developers.google.com/pay/api/web/guides/brand-guidelines?hl=ru](https://developers.google.com/pay/api/web/guides/brand-guidelines?hl=ru) +- Google Pay and Wallet APIs Acceptable Use Policy: [https://payments.developers.google.com/terms/aup?hl=ru](https://payments.developers.google.com/terms/aup?hl=ru) +- Google Pay API Terms of Service [https://payments.developers.google.com/terms/sellertos](https://payments.developers.google.com/terms/sellertos) + +## Əməliyyat axını + +- Müştəri internet mağazanın veb-saytında məhsul seçir. +- Satıcı Kapital Bank-a Create Order əməliyyatını yerinə yetirmək üçün sorğu göndərərək sifariş yaradır. + +Sorğu + +POST /order + +``` +{ + "order": { + "typeRid":"GN3D", + "amount":"1.0", + "currency":"AZN", + "description": "Testdesc" + } +} +``` + +Cavab + +``` +{ + "order": { + "id": 29575, + "hppUrl": "https://txpgtst.kapitalbank.az/flex", + "password": "113bl56jgrz5l", + "status": "Preparing", + "cvv2AuthStatus": "Required", + "secret": "513391" + } +} +``` + +Qeyd: İki əməliyyat növü (Cryptogram3DS və PAN_ONLY) üçün müxtəlif typeRid dəyərlərindən istifadə edilməlidir. Varsayılan olaraq Cryptogram3DS üçün GN3D, PAN_ONLY üçün isə GSMS istifadə olunur. Bu dəyərlər terminal parametrlərinizdən asılı olaraq fərqlənə bilər və kuratorunuz tərəfindən ayrıca təqdim ediləcək. + +- Kapital Bank sifarişi yaradır və sifariş ID-si və digər məlumatlarla birlikdə cavab göndərir. +- Müştəri Google Pay™ ilə ödəniş seçir. +- Müştəriyə Google Pay™ xidmətinin dialoq pəncərəsi göstərilir, Google hesabına giriş etmək, kart və çatdırılma ünvanını seçmək təklif olunur. +- Satıcı Google Pay™ ödəniş məlumatlarını googlePayBlock parametrində Kapital Bank-a göndərir. Kapital Bank, şifrələmə açarından istifadə edərək məlumatları deşifrə edir və sifariş məlumatlarını təhlil edir. Bunun nəticəsində 3DS v1.x / 3DS v2.x protokolu ilə doğrulama tələb oluna bilər. Bu sorğuda satıcı ödəniş tokenindən alınan JSON-u HEX formatında göndərməlidir. + +Sorğu + +/order/{{OrderId}}/set-src-token + +``` +{ + "token": { + "googlePayBlock": "7B227369676E6174757265223A224D4559434951432B354F6C3748565A657A585174574C6A3667735074324A2F3671554D4E302B4A4134314E49466C657357514968414C3249685545646376305363646A626246377436553078305655334B666D444830574D306B515933617766222C22696E7465726D6564696174655369676E696E674B6579223A7B227369676E65644B6579223A227B5C226B657956616C75655C223A5C224D466B77457759484B6F5A497A6A3043415159494B6F5A497A6A3044415163445167414544713939545136702B6F76342F624E7136706C4E2B79547943324975646B4476697A6B6E456B466B734936476B4C742F65734C4E4A385A78644B44476D6A79305472646447423074725275483452535A6A66443778515C5C75303033645C5C75303033645C222C5C226B657945787069726174696F6E5C223A5C22313733323236303937333038395C227D222C227369676E617475726573223A5B224D4555434951446B383746656C4F52507062556C513637545039484E3838533048423658756635745551573276787A7050674967576C382F4A347276626A6971707630364544475A49736773425357367038626B4A486D69334852667446555C7530303364225D7D2C2270726F746F636F6C56657273696F6E223A2245437632222C227369676E65644D657373616765223A227B5C22656E637279707465644D6573736167655C223A5C224F2B3534746E2B7051426B763543376746694230776E7A6D39594A7853686C643953796C776D6F61474D6C446F7A3541735433564A4E3464416A7977454537517844686F58337A4C47687734693152706F34767147517642424F4F70796A38634758363370474E38483845364965724D47684846355836333066702B4D464B784F476A784D734667566C76445241497335573074762B36634D4B5A6F7662376D56504D75677664736F48535A2F713441545A42375549334A736E7144496A4C79515633674E47614C694D30424B57446D4841426B416F76785A736E65306C4273334A6C756257724B6E642F4D6962524556744954717A424B57376A76556C4A70377042394F754339676C50675842784735473575346E336E59322B51313344494B6B48774E5A6E59764F626D754D684579442F6274624C655A454E777233614B55477035677566794A6774555148616B4E46336569484452566E68726E6C49337275467835762B682B5238484257366E5864646278423658637638433049323571583552365A4E6C51685237617A6F2F6E59755938367632776C6E734B4D5835782B756A6A356C75344A624237476A5A49697364744177414F6570666C4854643133694872664667794E426E787277483453425A4149316F48613137674E5769694C644B517365364C39524D35314E52454B696875564D4D724E3641724A59422F5472766B6A517A3672746162796A374D54497677574E74513550745630414D4477536447446353783453756E515C5C75303033645C5C75303033645C222C5C22657068656D6572616C5075626C69634B65795C223A5C224250684A563543627A6735556A5A2F31725761665576634E496C4747663672486C43326E386731474868592B6135344D702B6156356F4B752F782B66706B4C63566D36447170332F70555A6473384648714678464E79345C5C75303033645C222C5C227461675C223A5C224A4565536161524957512F6843706565494F737062734A51365078533359336E744A6C4B546275475A706B5C5C75303033645C227D227D" + } +} +``` + +Sorğu + +``` + + { + "order": { + "status": "Preparing", + "cvv2AuthStatus": "IneligibleOrder", + "tdsV1AuthStatus": "IneligibleOrder", + "tdsV2AuthStatus": "IneligibleOrder", + "otpAutStatus": "IneligibleOrder", + "srcToken": { + "id": 23516, + "paymentMethod": "GooglePay", + "role": "Src", + "status": "Active", + "regTime": "2024-11-15 10:58:36", + "displayName": "411111******1111", + "card": { + "expiration": "1226", + "brand": "Visa" + } + } + } +} +``` + +- Kapital Bank-dan cavab alındıqdan sonra satıcı, ödənişi maliyyələşdirmək üçün Execute Order Transaction əməliyyatını Kapital Bank-a göndərir. + +Sorğu + +/order/{{OrderId}}/exec-tran + +``` +{ + "tran":{ + "phase":"Single", + } +} +``` + +- Maliyyə əməliyyatının nəticəsindən asılı olaraq, Kapital Bank sifarişə müvafiq status verir: Tam ödənilib / Əməliyyat rədd edildi. +- Satıcı, müştəriyə sifariş haqqında məlumatı internet mağazanın veb-saytında göstərir. + +## Ödəniş Statusları + +| | +| + +## Errorlar + +| | +| + +## PmoDecline Kodları (Processing Error codes) + +| | +| diff --git a/docs/az/docs/integrations/lsim/index.md b/docs/az/docs/integrations/lsim/index.md index ea6b424..8790d3e 100644 --- a/docs/az/docs/integrations/lsim/index.md +++ b/docs/az/docs/integrations/lsim/index.md @@ -5,7 +5,35 @@ ## Rəsmi Dokumentasiya (v2024.11.22) { #official-documentation } -[İngliscə](https://mmzeynalli.notion.site/LSIM-1974f14f727e8029a3f5f9e4e556afe3?pvs=74) +[İngliscə](./official/api.md) + +## Sürətli başlanğıc { #quickstart } + +Tək və toplu SMS göndərmək, balansı yoxlamaq: + +```python +from integrify.lsim import LSIMBulkSMSClient, LSIMSingleSMSClient + +# Tək SMS (LSIM_LOGIN, LSIM_PASSWORD, LSIM_SENDER_NAME mühit dəyişənlərindən götürülür) +resp = LSIMSingleSMSClient.send_sms_post(msisdn='994501234567', text='Salam!') + +if resp.ok: + print(resp.body.obj) # tranzaksiya ID-si (hesabat üçün lazımdır) + +# Toplu SMS: hamıya eyni mətn +bulk = LSIMBulkSMSClient.bulk_send_one_message( + controlid=1, # hər göndəriş üçün unikal olmalıdır + msisdns=['994501234567', '994551234567'], + bulkmessage='Salam!', +) +print(bulk.body.task_id) + +# Balans +balance = LSIMSingleSMSClient.check_balance() +print(balance.body.obj) +``` + +Asinxron istifadə üçün `LSIMSingleSMSAsyncClient`/`LSIMBulkSMSAsyncClient` import edib, eyni metodları `await` ilə çağırın. ## Sorğular listi { #list-of-requests } diff --git a/docs/az/docs/integrations/lsim/official/api.md b/docs/az/docs/integrations/lsim/official/api.md new file mode 100644 index 0000000..c4893ce --- /dev/null +++ b/docs/az/docs/integrations/lsim/official/api.md @@ -0,0 +1,414 @@ +# LSIM SMS API + +???+ info + Bu səhifə LSIM-in rəsmi API sənədlərinin (tək SMS və toplu SMS) Markdown versiyasıdır. + Kitabxananın bu sorğulara uyğun metodları üçün [LSIM](../index.md) səhifəsinə baxın. + +## Single SMS sending API + +### Send SMS — HTTP GET + +**URL** + +```text +http(s)://apps.lsim.az/quicksms/v1/send?login=LOGIN&msisdn=MSISDN&text=MSG_BODY&sender=SENDER&key=KEY[&unicode=UNICODE] +``` + +**Method:** `GET` + +| Parameter | Description | +|---|---| +| `LOGIN` | Your login. | +| `MSISDN` | Subscriber number: country code + operator code + number. Example: `99450XXXXXXX`. | +| `MSG_BODY` | Message text. | +| `SENDER` | Sender title to use when sending the message. | +| `KEY` | `md5((md5(password)) + LOGIN + MSG_BODY + MSISDN + SENDER)` | +| `UNICODE` | Optional. `false` by default; use `true` when `MSG_BODY` contains Unicode characters. | + +**Response** + +```json +{"successMessage":null,"errorMessage":null,"obj":long,"errorCode":integer} +``` + +| Field | Description | +|---|---| +| `successMessage` | Success message of the operation. | +| `errorMessage` | Error message if an error occurred. | +| `obj` | Integer representing the transaction ID. | +| `errorCode` | Error code if an error occurred. | + +Parameters in square brackets are optional. Use optional parameters without the brackets. Before using Unicode, consult the provider's Unicode documentation. + +### Send SMS — HTTP POST + +**URL:** `https://apps.lsim.az/quicksms/v1/smssender` + +**Method:** `POST` + +**Request body** + +```json +{ + "login": "LOGIN", + "key": "md5((md5(password)) + LOGIN + MSG_BODY + MSISDN + SENDER)", + "msisdn": "99450XXXXXXX", + "text": "message body", + "sender": "sender title", + "scheduled": "NOW", + "unicode": false +} +``` + +| Field | Description | +|---|---| +| `login` | Your login. | +| `key` | `md5((md5(password)) + LOGIN + MSG_BODY + MSISDN + SENDER)` | +| `msisdn` | Subscriber number in country-code format. Example: `99450XXXXXXX`. | +| `text` | Message body. | +| `sender` | Sender title to use when sending the message. | +| `scheduled` | `NOW` or a date-time such as `2023-05-19 15:40:05`. Defaults to `NOW`. | +| `unicode` | `false` or `true`. Defaults to `false`. | + +**Response** + +```json +{"successMessage":null,"errorMessage":null,"obj":long,"errorCode":integer} +``` + +### Check balance + +**URL** + +```text +http(s)://apps.lsim.az/quicksms/v1/balance?login=LOGIN&key=KEY +``` + +**Method:** `GET` + +| Parameter | Description | +|---|---| +| `LOGIN` | Your login. | +| `KEY` | `md5((md5(password)) + LOGIN)` | + +**Response** + +```json +{"successMessage":null,"errorMessage":null,"obj":integer,"errorCode":integer} +``` + +`obj` contains the current balance. + +### Get report — HTTP POST + +**URL:** `https://apps.lsim.az/quicksms/v1/smsreporter` + +**Method:** `POST` + +**Request body** + +```json +{ + "login": "LOGIN", + "transid": "TRANSACTION_ID" +} +``` + +`transid` is the transaction ID returned after a successful SMS submission. + +### Get report — HTTP GET + +**URL** + +```text +http(s)://apps.lsim.az/quicksms/v1/report?login=LOGIN&trans_id=TRANS_ID +``` + +**Method:** `GET` + +| Parameter | Description | +|---|---| +| `LOGIN` | Your login. | +| `TRANS_ID` | Transaction ID returned after a successful SMS submission. | + +### Delivery statuses + +| Code | Meaning | +|---:|---| +| `100` | In queue | +| `101` | Delivered | +| `102` | Undelivered | +| `103` | Expired | +| `104` | Rejected | +| `105` | Cancelled | +| `106` | Error | +| `107` | Unknown — contact support | +| `108` | Sent | +| `109` | Black list | + +### Error responses + +| Code | Meaning | +|---:|---| +| `-100` | Invalid key | +| `-101` | Text exceeds the allowed length | +| `-102` | Wrong number format | +| `-103` | Invalid sender name | +| `-104` | Insufficient balance | +| `-105` | Number is on the blacklist | +| `-106` | Invalid transaction ID | +| `-107` | IP address not allowed | +| `-108` | Invalid hash | +| `-109` | No host | +| `-110` | Reporting limit exceeded | +| `-500` | Internal error | + +**Reporting limit:** Since 2019-02-01, reporting is limited per minute. The default TPM limit is 150 transactions. The counter resets at the beginning of each minute. + +### Push delivery reports + +Delivery reports can be pushed to a URL over HTTP GET if a callback URL is provided in this form: + +```text +http[s]://hostname/?trans_id={trans_id}&status={status} +``` + +`{trans_id}` is replaced with the transaction ID, and `{status}` is replaced with one of the delivery status codes above. + +--- + +## Bulk SMS REST API + +**Endpoint:** [https://www.sendsms.az/smxml/api](https://www.sendsms.az/smxml/api) + +**Content type:** `application/json` + +### 1. Submit a bulk message + +Use `isbulk: true` to send the same message to multiple phone numbers. + +**Request** + +```json +{ + "request": { + "head": { + "operation": "submit", + "login": "your login", + "password": "your password", + "controlid": "generated control ID", + "title": "your sender name", + "scheduled": "NOW", + "isbulk": true, + "bulkmessage": "your message text" + }, + "body": [ + {"msisdn": "994XXXXXXXXX"}, + {"msisdn": "994XXXXXXXXX"} + ] + } +} +``` + +`controlid` should be generated to prevent multiple submissions of the same task. `scheduled` may be `NOW` or a time in `YYYY-MM-DD HH:mm:ss` format. Phone numbers use the `994XXXXXXXXX` format. + +**Response** + +```json +{ + "response": { + "head": {"responsecode": "000"}, + "body": {"taskid": "XXXXXXXX"} + } +} +``` + +### 2. Submit individual messages + +Use `isbulk: false` when each recipient needs a different message. + +**Request** + +```json +{ + "request": { + "head": { + "operation": "submit", + "login": "your login", + "password": "your password", + "controlid": "generated control ID", + "title": "your sender name", + "scheduled": "NOW", + "isbulk": false + }, + "body": [ + { + "msisdn": "994XXXXXXXXX", + "message": "message text for phone number 1" + }, + { + "msisdn": "994XXXXXXXXX", + "message": "message text for phone number 2" + } + ] + } +} +``` + +**Response** + +```json +{ + "response": { + "head": {"responsecode": "000"}, + "body": {"taskid": "XXXXXXXX"} + } +} +``` + +### 3. Get a message-status report + +**Request** + +```json +{ + "request": { + "head": { + "operation": "report", + "login": "your login", + "password": "your password", + "taskid": "XXXXXXXX" + } + } +} +``` + +**Response** + +```json +{ + "response": { + "head": {"responsecode": "000"}, + "body": { + "expired": 0, + "removed": 0, + "blackList": 0, + "undelivered": 0, + "delivered": 1, + "duplicate": 0, + "error": 0, + "send": 0, + "queue": 0 + } + } +} +``` + +### 4. Get a detailed status report + +**Request** + +```json +{ + "request": { + "head": { + "operation": "detailedreport", + "login": "your login", + "password": "your password", + "taskid": "XXXXXXXX" + } + } +} +``` + +**Response** + +```json +{ + "response": { + "head": {"responsecode": "000"}, + "body": [ + { + "msisdn": "994XXXXXXXXX", + "message": "message text", + "status": 2 + } + ] + } +} +``` + +### 5. Get a detailed report with dates + +**Request** + +```json +{ + "request": { + "head": { + "operation": "detailedreportwithdate", + "login": "your login", + "password": "your password", + "taskid": "XXXXXXXX" + } + } +} +``` + +**Response** + +```json +{ + "response": { + "head": {"responsecode": "000"}, + "body": [ + { + "date": "YYYY-MM-DD HH:mm:ss", + "msisdn": "994XXXXXXXXX", + "message": "message text", + "status": 2 + } + ] + } +} +``` + +### Bulk API status codes + +| Code | Meaning | +|---:|---| +| `1` | Message expired | +| `2` | Message successfully delivered | +| `3` | Message undelivered | +| `4` | Message sent | +| `5` | System error | +| `6` | Blacklist | +| `7` | Message is in the queue | +| `8` | Duplicate message | + +### 6. Get current SMS balance + +**Request** + +```json +{ + "request": { + "head": { + "operation": "units", + "login": "your login", + "password": "your password" + } + } +} +``` + +**Response** + +```json +{ + "response": { + "head": {"responsecode": "000"}, + "body": {"units": 13} + } +} +``` diff --git a/docs/az/docs/integrations/posta-guvercini/index.md b/docs/az/docs/integrations/posta-guvercini/index.md index c93a834..696452e 100644 --- a/docs/az/docs/integrations/posta-guvercini/index.md +++ b/docs/az/docs/integrations/posta-guvercini/index.md @@ -7,6 +7,28 @@ [İngliscə](https://www.poctgoyercini.com/api_json/swagger/ui/index#/) +Markdown versiyası (bu saytda): [Posta Güvərçini API](./official/api.md) + +## Sürətli başlanğıc { #quickstart } + +SMS göndərmək və statusunu yoxlamaq: + +```python +from integrify.postaguvercini import PostaGuverciniClient + +resp = PostaGuverciniClient.send_single_sms(message='Salam!', receivers=['994501234567']) + +if resp.ok: + message_id = resp.body.result[0].message_id + + status = PostaGuverciniClient.get_status(message_ids=[message_id]) + print(status.body.result[0].sms_status_description) +else: + print(resp.body.status_description) +``` + +Asinxron istifadə üçün `PostaGuverciniAsyncClient` import edib, eyni metodları `await` ilə çağırın. + ## Sorğular listi { #list-of-requests } | Sorğu metodu | Məqsəd | PostaGuvercini API | diff --git a/docs/az/docs/integrations/posta-guvercini/official/api.md b/docs/az/docs/integrations/posta-guvercini/official/api.md new file mode 100644 index 0000000..9383474 --- /dev/null +++ b/docs/az/docs/integrations/posta-guvercini/official/api.md @@ -0,0 +1,341 @@ +# Posta Guvercini SMS Service (v1) + +???+ info + Bu səhifə Posta Güvərçini-nin rəsmi Swagger spesifikasiyasının ([Swagger UI](https://www.poctgoyercini.com/api_json/swagger/ui/index#/)) Markdown versiyasıdır. Sorğu/cavab nümunələri spesifikasiyadakı modellərdən yaradılıb. Uyğunsuzluq olarsa, orijinal mənbə əsas götürülür. + +Base URL: `https://www.poctgoyercini.com/api_json` + +## Endpoints + +### POST `/v1/Sms/Send_1_N` + +It is the method that can be used in cases where there is 1 sms text and N recipients. + +- If the StatusCode value is other than 200, it means there is an error or validation problem. Request parameters and StatusDescription should be checked. +- Requests should be made in packages containing 800 recipients each. + +Content-Type: `application/json`, `text/json`, `application/xml`, `text/xml`, `application/x-www-form-urlencoded` + +**Request body** (`RequestSmsSend_1_N`): + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `Message` | string | Yes | Indicates the text of the SMS. It cannot be empty. | +| `Receivers` | string[] | Yes | Indicates the recipients of the SMS. It cannot be empty. Example: `905320000000` | +| `SendDate` | string | No | Indicates the time to send the SMS. When it is blank, sms will be sent immediately. When a valid date is passed, an sms will be sent when the time has passed. Format: yyyyMMdd HH:mm Example: `20200630 15:00` | +| `ExpireDate` | string | No | Indicates the last time the SMS will be attempted to be sent. When it is blank, the time determined by the system will be valid. Format: yyyyMMdd HH:mm Example: `20200701 14:00` | +| `Channel` | string | No | Indicates on which platform (OTP or BULK) the sms will be sent with the originator. Example: `OTP` | +| `Originator` | string | No | It is a field to be used when it is desired to send sms under different originators with a single account. The information to be sent will be given by the customer service representative and is an 11-character value. | +| `Username` | string | Yes | Refers to the username of the account in the Posta Guvercini SMS System. It cannot be empty. | +| `Password` | string | Yes | Refers to the password of the account in the Posta Guvercini SMS System. It cannot be empty. | + +```json +{ + "Message": "string", + "Receivers": [ + "string" + ], + "SendDate": "string", + "ExpireDate": "string", + "Channel": "string", + "Originator": "string", + "Username": "string", + "Password": "string" +} +``` + +**Response 200** — OK (`ApiResponse[List[ResponseSmsSendObject]]`): + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `StatusCode` | integer (int32) — 200, 400, 500, 1020, 1030, 1040, 1050, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1070, 1090, 2060 | No | Indicates the status of the response to the request. | +| `StatusDescription` | string | No | Indicates a detailed explanation of the response to the request made. | +| `Result` | ResponseSmsSendObject[] | No | Indicates the data to be returned in response to the request. | + +```json +{ + "StatusCode": 0, + "StatusDescription": "string", + "Result": [ + { + "MessageId": "string", + "Receiver": "string", + "Charge": 0 + } + ] +} +``` + +### POST `/v1/Sms/Send_N_N` + +It is the method that can be used in cases where there is N sms text and N recipients. + +- If the StatusCode value is other than 200, it means there is an error or validation problem. Request parameters and StatusDescription should be checked. +- Requests should be made in packages containing 800 recipients each. + +Content-Type: `application/json`, `text/json`, `application/xml`, `text/xml`, `application/x-www-form-urlencoded` + +**Request body** (`RequestSmsSend_N_N`): + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `Messages` | RequestSmsObject_N_N[] | Yes | It refers to the text of the SMS and its recipients. It cannot be empty. | +| `SendDate` | string | No | Indicates the time to send the SMS. When it is blank, sms will be sent immediately. When a valid date is passed, an sms will be sent when the time has passed. Format: yyyyMMdd HH:mm Example: `20200630 15:00` | +| `ExpireDate` | string | No | Indicates the last time the SMS will be attempted to be sent. When it is blank, the time determined by the system will be valid. Format: yyyyMMdd HH:mm Example: `20200701 14:00` | +| `Channel` | string | No | Indicates on which platform (OTP or BULK) the sms will be sent with the originator. Example: `OTP` | +| `Originator` | string | No | It is a field to be used when it is desired to send sms under different originators with a single account. The information to be sent will be given by the customer service representative and is an 11-character value. | +| `Username` | string | Yes | Refers to the username of the account in the Posta Guvercini SMS System. It cannot be empty. | +| `Password` | string | Yes | Refers to the password of the account in the Posta Guvercini SMS System. It cannot be empty. | + +```json +{ + "Messages": [ + { + "Receiver": "string", + "Message": "string" + } + ], + "SendDate": "string", + "ExpireDate": "string", + "Channel": "string", + "Originator": "string", + "Username": "string", + "Password": "string" +} +``` + +**Response 200** — OK (`ApiResponse[List[ResponseSmsSendObject]]`): + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `StatusCode` | integer (int32) — 200, 400, 500, 1020, 1030, 1040, 1050, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1070, 1090, 2060 | No | Indicates the status of the response to the request. | +| `StatusDescription` | string | No | Indicates a detailed explanation of the response to the request made. | +| `Result` | ResponseSmsSendObject[] | No | Indicates the data to be returned in response to the request. | + +```json +{ + "StatusCode": 0, + "StatusDescription": "string", + "Result": [ + { + "MessageId": "string", + "Receiver": "string", + "Charge": 0 + } + ] +} +``` + +### POST `/v1/Sms/Status` + +It is the method to checking the status of sent SMSs. + +- If the StatusCode value is other than 200, it means there is an error or validation problem. Request parameters and StatusDescription should be checked. +- Requests should be made in packages containing 800 recipients each. + +Content-Type: `application/json`, `text/json`, `application/xml`, `text/xml`, `application/x-www-form-urlencoded` + +**Request body** (`RequestSmsStatus`): + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `MessageIds` | string[] | Yes | It refers to the message Id in the Posta Guvercini SMS System of Sms. Example: `EZ_43D2B5QC-FD3A-406G-8C5B-D079F24FD400` | +| `Username` | string | Yes | Refers to the username of the account in the Posta Guvercini SMS System. It cannot be empty. | +| `Password` | string | Yes | Refers to the password of the account in the Posta Guvercini SMS System. It cannot be empty. | + +```json +{ + "MessageIds": [ + "string" + ], + "Username": "string", + "Password": "string" +} +``` + +**Response 200** — OK (`ApiResponse[List[ResponseSmsStatusObject]]`): + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `StatusCode` | integer (int32) — 200, 400, 500, 1020, 1030, 1040, 1050, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1070, 1090, 2060 | No | Indicates the status of the response to the request. | +| `StatusDescription` | string | No | Indicates a detailed explanation of the response to the request made. | +| `Result` | ResponseSmsStatusObject[] | No | Indicates the data to be returned in response to the request. | + +```json +{ + "StatusCode": 0, + "StatusDescription": "string", + "Result": [ + { + "MessageId": "string", + "Receiver": "string", + "SmsStatus": "string", + "SmsStatusDescription": "string", + "IsFinalStatus": "string", + "StatusTime": "string", + "SmsCharge": "string" + } + ] +} +``` + +### POST `/v1/Sms/CreditBalance` + +It is the method to checking the account balance. + +- If the StatusCode value is other than 200, it means there is an error or validation problem. Request parameters and StatusDescription should be checked. + +Content-Type: `application/json`, `text/json`, `application/xml`, `text/xml`, `application/x-www-form-urlencoded` + +**Request body** (`RequestCreditBalance`): + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `Username` | string | Yes | Refers to the username of the account in the Posta Guvercini SMS System. It cannot be empty. | +| `Password` | string | Yes | Refers to the password of the account in the Posta Guvercini SMS System. It cannot be empty. | + +```json +{ + "Username": "string", + "Password": "string" +} +``` + +**Response 200** — OK (`ApiResponse[ResponseCreditBalanceObject]`): + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `StatusCode` | integer (int32) — 200, 400, 500, 1020, 1030, 1040, 1050, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1070, 1090, 2060 | No | Indicates the status of the response to the request. | +| `StatusDescription` | string | No | Indicates a detailed explanation of the response to the request made. | +| `Result` | ResponseCreditBalanceObject | No | Indicates the data to be returned in response to the request. | + +```json +{ + "StatusCode": 0, + "StatusDescription": "string", + "Result": { + "Balance": 0 + } +} +``` + +## Models + +### `RequestSmsSend_1_N` + +It is a 1_N type SMS sending model. + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `Message` | string | Yes | Indicates the text of the SMS. It cannot be empty. | +| `Receivers` | string[] | Yes | Indicates the recipients of the SMS. It cannot be empty. Example: `905320000000` | +| `SendDate` | string | No | Indicates the time to send the SMS. When it is blank, sms will be sent immediately. When a valid date is passed, an sms will be sent when the time has passed. Format: yyyyMMdd HH:mm Example: `20200630 15:00` | +| `ExpireDate` | string | No | Indicates the last time the SMS will be attempted to be sent. When it is blank, the time determined by the system will be valid. Format: yyyyMMdd HH:mm Example: `20200701 14:00` | +| `Channel` | string | No | Indicates on which platform (OTP or BULK) the sms will be sent with the originator. Example: `OTP` | +| `Originator` | string | No | It is a field to be used when it is desired to send sms under different originators with a single account. The information to be sent will be given by the customer service representative and is an 11-character value. | +| `Username` | string | Yes | Refers to the username of the account in the Posta Guvercini SMS System. It cannot be empty. | +| `Password` | string | Yes | Refers to the password of the account in the Posta Guvercini SMS System. It cannot be empty. | + +### `ApiResponse[List[ResponseSmsSendObject]]` + +Indicates the model to return in response to API requests. + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `StatusCode` | integer (int32) — 200, 400, 500, 1020, 1030, 1040, 1050, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1070, 1090, 2060 | No | Indicates the status of the response to the request. | +| `StatusDescription` | string | No | Indicates a detailed explanation of the response to the request made. | +| `Result` | ResponseSmsSendObject[] | No | Indicates the data to be returned in response to the request. | + +### `ResponseSmsSendObject` + +It is the model that sms sending methods will return as a reply. + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `MessageId` | string | No | It is the unique id information in the Posta Guvercini SMS system of Sms. This id information should be kept if Sms status checking is to be made. | +| `Receiver` | string | No | It is the recipient address sent to the API during the sms sending request. | +| `Charge` | integer (int32) | No | Indicates the estimated number of sms the message will be charged with. | + +### `RequestSmsSend_N_N` + +It is N_N type SMS sending model. + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `Messages` | RequestSmsObject_N_N[] | Yes | It refers to the text of the SMS and its recipients. It cannot be empty. | +| `SendDate` | string | No | Indicates the time to send the SMS. When it is blank, sms will be sent immediately. When a valid date is passed, an sms will be sent when the time has passed. Format: yyyyMMdd HH:mm Example: `20200630 15:00` | +| `ExpireDate` | string | No | Indicates the last time the SMS will be attempted to be sent. When it is blank, the time determined by the system will be valid. Format: yyyyMMdd HH:mm Example: `20200701 14:00` | +| `Channel` | string | No | Indicates on which platform (OTP or BULK) the sms will be sent with the originator. Example: `OTP` | +| `Originator` | string | No | It is a field to be used when it is desired to send sms under different originators with a single account. The information to be sent will be given by the customer service representative and is an 11-character value. | +| `Username` | string | Yes | Refers to the username of the account in the Posta Guvercini SMS System. It cannot be empty. | +| `Password` | string | Yes | Refers to the password of the account in the Posta Guvercini SMS System. It cannot be empty. | + +### `RequestSmsObject_N_N` + +It is a N_N type SMS sending model. + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `Receiver` | string | Yes | Indicates the recipients of the SMS. It cannot be empty. Example: `905320000000` | +| `Message` | string | Yes | Indicates the text of the SMS. It cannot be empty. | + +### `RequestSmsStatus` + +It is sms status checking model. + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `MessageIds` | string[] | Yes | It refers to the message Id in the Posta Guvercini SMS System of Sms. Example: `EZ_43D2B5QC-FD3A-406G-8C5B-D079F24FD400` | +| `Username` | string | Yes | Refers to the username of the account in the Posta Guvercini SMS System. It cannot be empty. | +| `Password` | string | Yes | Refers to the password of the account in the Posta Guvercini SMS System. It cannot be empty. | + +### `ApiResponse[List[ResponseSmsStatusObject]]` + +Indicates the model to return in response to API requests. + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `StatusCode` | integer (int32) — 200, 400, 500, 1020, 1030, 1040, 1050, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1070, 1090, 2060 | No | Indicates the status of the response to the request. | +| `StatusDescription` | string | No | Indicates a detailed explanation of the response to the request made. | +| `Result` | ResponseSmsStatusObject[] | No | Indicates the data to be returned in response to the request. | + +### `ResponseSmsStatusObject` + +It is the model that sms status methods will return as a response. + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `MessageId` | string | No | It is the unique id information in the Posta Guvercini SMS system of Sms. | +| `Receiver` | string | No | It refers to the recipient of the sms. | +| `SmsStatus` | string | No | Indicates the status of the sms. | +| `SmsStatusDescription` | string | No | It refers to the description of the status of the sms. | +| `IsFinalStatus` | string | No | Indicates whether the SMS has reached its final state or not. If the Sms has reached its final status, its status will no longer be updated. Inquiries should no longer be made for this sms. 0: Final state not yet reached 1: Final state reached. No more inquiries should be made. | +| `StatusTime` | string | No | If the sms has reached the recipient (Status=400), it means the time of arrival. In other cases, it refers to the time when the last status change of the sms was made. Format: yyyyMMdd HH:mm Example: `20200630 16:08` | +| `SmsCharge` | string | No | Indicates the number of sms charged. If IsFinalStatus = 1, valid data is returned. | + +### `RequestCreditBalance` + +It is sms status checking model. + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `Username` | string | Yes | Refers to the username of the account in the Posta Guvercini SMS System. It cannot be empty. | +| `Password` | string | Yes | Refers to the password of the account in the Posta Guvercini SMS System. It cannot be empty. | + +### `ApiResponse[ResponseCreditBalanceObject]` + +Indicates the model to return in response to API requests. + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `StatusCode` | integer (int32) — 200, 400, 500, 1020, 1030, 1040, 1050, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1070, 1090, 2060 | No | Indicates the status of the response to the request. | +| `StatusDescription` | string | No | Indicates a detailed explanation of the response to the request made. | +| `Result` | ResponseCreditBalanceObject | No | Indicates the data to be returned in response to the request. | + +### `ResponseCreditBalanceObject` + +It is the model that sms status methods will return as a response. + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `Balance` | integer (int32) | No | Indicates the number of sms charged. If IsFinalStatus = 1, valid data is returned. | diff --git a/docs/az/mkdocs.yml b/docs/az/mkdocs.yml index 2538d18..7b97279 100644 --- a/docs/az/mkdocs.yml +++ b/docs/az/mkdocs.yml @@ -133,6 +133,7 @@ nav: - Schemas: - Response: integrations/kapitalbank/api-reference/response.md - "Utils & Enums": integrations/kapitalbank/api-reference/utils.md + - Rəsmi Dokumentasiya: integrations/kapitalbank/official/api.md - Azericard: - integrations/azericard/index.md - integrations/azericard/env.md @@ -143,6 +144,7 @@ nav: - Callback: integrations/azericard/api-reference/callback.md - Common: integrations/azericard/api-reference/common-schemas.md - Helpers: integrations/azericard/api-reference/helper-functions.md + - Rəsmi Dokumentasiya: integrations/azericard/official/api.md - LSIM: - integrations/lsim/index.md - integrations/lsim/env.md @@ -157,6 +159,7 @@ nav: - Schemas: - Response: integrations/lsim/api-reference/bulk/response.md - Enums: integrations/lsim/api-reference/bulk/enums.md + - Rəsmi Dokumentasiya: integrations/lsim/official/api.md - Posta Güvərçini: - integrations/posta-guvercini/index.md - integrations/posta-guvercini/env.md @@ -164,6 +167,7 @@ nav: - integrations/posta-guvercini/api-reference/client.md - Schemas: - Response: integrations/posta-guvercini/api-reference/response.md + - Rəsmi Dokumentasiya: integrations/posta-guvercini/official/api.md # Private section (separate build, password-protected): see docs/private.yml - E-Customs (məxfi): - E-Customs: /private/ecustoms/ diff --git a/docs/az/partial.yml b/docs/az/partial.yml deleted file mode 100644 index 5b63ec7..0000000 --- a/docs/az/partial.yml +++ /dev/null @@ -1,54 +0,0 @@ -Core (Daxili): "integrations/core/api-reference.md" - -EPoint: - - "integrations/epoint/index.md" - - "integrations/epoint/env.md" - - API Referansı: - - "integrations/epoint/api-reference/client.md" - - Schemas: - - Response: "integrations/epoint/api-reference/response.md" - - Callback: "integrations/epoint/api-reference/callback.md" - - "integrations/epoint/api-reference/helper-functions.md" - -Kapital Bank: - - "integrations/kapitalbank/index.md" - - "integrations/kapitalbank/env.md" - - API Referansı: - - "integrations/kapitalbank/api-reference/client.md" - - Schemas: - - Response: "integrations/kapitalbank/api-reference/response.md" - - Utils & Enums: "integrations/kapitalbank/api-reference/utils.md" - -Azericard: - - "integrations/azericard/index.md" - - "integrations/azericard/env.md" - - API Referansı: - - "integrations/azericard/api-reference/client.md" - - Schemas: - - Response: "integrations/azericard/api-reference/response.md" - - Callback: "integrations/azericard/api-reference/callback.md" - - Common: "integrations/azericard/api-reference/common-schemas.md" - - Helpers: "integrations/azericard/api-reference/helper-functions.md" - -LSIM: - - "integrations/lsim/index.md" - - "integrations/lsim/env.md" - - API Referansı: - - Single SMS: - - "integrations/lsim/api-reference/single/client.md" - - Schemas: - - Response: "integrations/lsim/api-reference/single/response.md" - - Enums: "integrations/lsim/api-reference/single/enums.md" - - Bulk SMS: - - "integrations/lsim/api-reference/bulk/client.md" - - Schemas: - - Response: "integrations/lsim/api-reference/bulk/response.md" - - Enums: "integrations/lsim/api-reference/bulk/enums.md" - -Posta Guvercini: - - "integrations/posta-guvercini/index.md" - - "integrations/posta-guvercini/env.md" - - API Referansı: - - "integrations/posta-guvercini/api-reference/client.md" - - Schemas: - - Response: "integrations/posta-guvercini/api-reference/response.md" diff --git a/docs/en/docs/integrations/clopos/index.md b/docs/en/docs/integrations/clopos/index.md index 53666f1..ae8b902 100644 --- a/docs/en/docs/integrations/clopos/index.md +++ b/docs/en/docs/integrations/clopos/index.md @@ -7,6 +7,11 @@ [English](https://developer.clopos.com/) +Markdown version (on this site): [Clopos Open API (v2)](./official/api.md) + +!!! warning + Clopos marks the v2 API that this package uses as deprecated. It still works, but new endpoints only go to the new [Clopos Open API](https://developer.clopos.com/docs/api-reference/open-api/overview). + ## List of requests { #list-of-requests } | Request function | Purpose | Clopos API | @@ -38,4 +43,24 @@ First of all, one should use `auth` method to acquire token. This token is used in all future API calls. Bear in mind that, these tokens are active for one hour. After one hour, token automatically expires, and you should again use `auth` to get a new one. This workflow responsibility falls on user. -After acquiring token, for any subsequent call, just use `headers={'token': token}` argument for any call. For other arguments that specific APIs might need, please check [API reference](api-reference/client.md). +After acquiring token, for any subsequent call, just use `headers={'x-token': token}` argument for any call. For other arguments that specific APIs might need, please check [API reference](api-reference/client.md). + +## Quick start { #quickstart } + +```python +from integrify.clopos import CloposRequest + +# 1. Get a token (uses the CLOPOS_* environment variables). Tokens are valid for one hour. +auth = CloposRequest.auth() +headers = {'x-token': auth.body.token} + +# 2. Pass the token to every request +products = CloposRequest.get_products(limit=10, headers=headers) +for product in products.body.data: + print(product.id, product.name) + +orders = CloposRequest.get_orders(limit=5, headers=headers) +print(orders.body.total) +``` + +For async usage, import `CloposAsyncRequest` and `await` the same methods. diff --git a/docs/en/docs/integrations/clopos/official/api.md b/docs/en/docs/integrations/clopos/official/api.md new file mode 100644 index 0000000..98839f9 --- /dev/null +++ b/docs/en/docs/integrations/clopos/official/api.md @@ -0,0 +1,6842 @@ +# Clopos Open API (v2) + +???+ info + This page is a Markdown version of the v2 API reference from the official Clopos developer docs ([developer.clopos.com](https://developer.clopos.com/docs)), which is the API this package uses. If anything differs, the original is authoritative. + +!!! warning + Clopos marks this API (`integrations.clopos.com/open-api`) as deprecated: it still works and existing integrations keep running, but it no longer gets new endpoints and will eventually be retired. New integrations should use the [Clopos Open API](https://developer.clopos.com/docs/api-reference/open-api/overview) on `open-api.clopos.com`. See [Migrating](https://developer.clopos.com/docs/migrating). + +## Authentication + +### Authenticate (v2) + +Source: + +`POST /v2/auth` + +Exchange client credentials for a JWT access token + +#### Purpose + +Request a short-lived JWT that authorizes all other v2 API calls. + +#### HTTP Request + +```http +POST https://integrations.clopos.com/open-api/v2/auth +``` + +#### Where the credentials come from + +The four values in the request body come from two different sources: + +* **`integrator_id`** — issued by Clopos. Every v2 integration must send one. Request it by filling out this form: [https://forms.gle/Y9P1Wnv4QFAruxny8](https://forms.gle/Y9P1Wnv4QFAruxny8) +* **`client_id`, `client_secret`, `brand`** — come from the Clopos customer you are integrating with. They generate the Client ID and Client Secret themselves in their back office under **Add-ons → Open API**, then share both values and their brand identifier with you. + +!!! note + See [Authentication](https://developer.clopos.com/docs/authentication#where-the-client-id-and-client-secret-come-from) for the step-by-step back office instructions to pass on to your customer. + +#### Request Example + +```bash +curl --location 'https://integrations.clopos.com/open-api/v2/auth' \ + --header 'Content-Type: application/json' \ + --data '{ + "client_id": "your_client_id_here", + "client_secret": "your_client_secret_here", + "brand": "your_brand", + "integrator_id": "your_integrator_id_here" + }' +``` + +##### Request body + +| Field | Type | Required | Description | +| --------------- | ------ | -------- | ----------------------------------------------------------------- | +| `client_id` | string | Yes | Generated in the customer's back office (**Add-ons → Open API**). | +| `client_secret` | string | Yes | Secret paired with the Client ID, generated at the same time. | +| `brand` | string | Yes | The customer's brand identifier. | +| `integrator_id` | string | Yes | New in v2. Identifies the integrator making the request. | + +`venue_id` is no longer part of the authentication payload. + +#### Response + +##### 200 OK — Token issued + +```json +{ + "success": true, + "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbiI6Im9hdXRoX1lOellQZE1QV21KeU0zOFVyblQzR3hoS25TelBNTHl2clB2UGgxQnRaeVFScTVzRWJsRkl5b3MwYVIyejMwWmYiLCJicmFuZCI6Im9tZWdhIiwic3RhZ2UiOiJiZXRhIiwidmVudWVfaWQiOjEsImludGVncmF0b3JfaWQiOiJ0ZXN0X2pLc1U5NnJxMzMzYjZQb3RUWmZrZ3ciLCJpYXQiOjE3Njc4NDg3MzIsImV4cCI6MTc2Nzg1MjMzMn0.7atyo3LEPXTyIjs2BjZIcUbWeFYtr375GeDwoVnWSRs", + "token_type": "Bearer", + "expires_in": 3600, + "expires_at": 1767852332, + "message": "Authentication successful" +} +``` + +##### How to use the token + +* Include only the `x-token` header on all other v2 endpoints: +```bash +x-token: +``` +* Tokens expire after `expires_in` seconds; `expires_at` indicates the epoch timestamp when the token becomes invalid. + +#### Integrator ID + +Some integrations need to access Clopos Open API without an end-user logging in. For these cases, an **Integrator ID** is required. + +!!! note + Request an Integrator ID by filling out this form: [Request Integrator ID](https://forms.gle/Y9P1Wnv4QFAruxny8) + +## Categories + +### List Categories + +Source: + +`GET /v2/categories` + +Retrieve product categories along with their hierarchical structure + +#### Purpose + +Allows you to retrieve your category tree, including subcategories, in a single call. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/categories +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Query Parameters + +- `` (integer): Page number for pagination (1-based). + +- `` (integer): Number of categories to return (1-999). + +- `` (integer): Filters records under a specific parent category. + +- `` (string): Category type; `PRODUCT`, `INGREDIENT`, `ACCOUNTING`. + +- `` (boolean): Include child categories in the response. + +- `` (boolean): Return inactive categories. + +#### Request Example + +```bash +curl -X GET "https://integrations.clopos.com/open-api/v2/categories?page=1&limit=20&filters%5B0%5D%5B0%5D=type&filters%5B0%5D%5B1%5D=PRODUCT" \ + -H "x-token: oauth_example_token" \ +``` + +```javascript +const params = new URLSearchParams({ + page: "1", + limit: "20", + "filters[0][0]": "type", + "filters[0][1]": "PRODUCT", + include_children: "true", +}); + +const response = await fetch( + `https://integrations.clopos.com/open-api/v2/categories?${params}`, + { + headers: { + "x-token": "oauth_example_token", + }, + }, +); + +const categories = await response.json(); +``` + +```python +import requests + +url = "https://integrations.clopos.com/open-api/v2/categories" +headers = { + "x-token": "oauth_example_token", +} +params = { + "page": 1, + "limit": 20, + "filters[0][0]": "type", + "filters[0][1]": "PRODUCT", + "include_children": True, +} + +response = requests.get(url, headers=headers, params=params) +result = response.json() +``` + +#### Response + +##### 200 OK — List of categories + +```json +{ + "success": true, + "data": [ + { + "id": 1, + "name": "Pizza", + "status": 1, + "hidden": false, + "type": "PRODUCT", + "position": null, + "parent_id": null, + "depth": 0, + "color": "00bcd4", + "children": [], + "media": [], + "created_at": "2026-01-28T18:23:53.000000Z", + "updated_at": "2026-01-28T18:23:53.000000Z" + }, + { + "id": 2, + "name": "Drinks", + "status": 1, + "hidden": false, + "type": "PRODUCT", + "position": null, + "parent_id": null, + "depth": 0, + "color": "00bcd4", + "children": [], + "media": [ + { + "uuid": "1d76f22b-c209-4fac-be3a-cfde7b8f0d74", + "mime_type": "image/jpeg", + "size": 87281, + "urls": { + "original": "https://cdn.clopos.com/omega/1d76f22b-.../original.jpg", + "extra_large": "https://cdn.clopos.com/omega/1d76f22b-.../extra_large.jpg", + "thumb": "https://cdn.clopos.com/omega/1d76f22b-.../thumb.jpg" + }, + "blur_hash": "LEIpFsE%t1}TxpENEgaK0iowRktQ", + "dimensions": { + "width": 612, + "height": 459 + } + } + ], + "created_at": "2026-02-13T16:31:36.000000Z", + "updated_at": "2026-02-13T16:31:36.000000Z" + } + ], + "total": 2 +} +``` + +##### 400 Bad Request — Parameter error + +```json +{ + "success": false, + "error": "invalid_parameter", + "message": "type must be one of PRODUCT, INGREDIENT, ACCOUNTING" +} +``` + +#### Field Reference + +##### Category Object + +| Field | Type | Description | +| ------------ | ------------------ | -------------------------------------------------------------------------------------------------------------- | +| `id` | integer | Unique identifier. | +| `name` | string | Category name. | +| `status` | integer | `1` = active, `0` = inactive. | +| `type` | string | `PRODUCT`, `INGREDIENT`, or `ACCOUNTING`. | +| `position` | integer (nullable) | Display order position. | +| `parent_id` | integer (nullable) | Parent category ID, `null` for root categories. | +| `_lft` | integer | Left boundary in the nested-set tree. Useful for ordering and subtree queries. | +| `_rgt` | integer | Right boundary in the nested-set tree. A category's descendants have `_lft` and `_rgt` values between its own. | +| `depth` | integer | Hierarchy level (`0` = root). | +| `color` | string | HEX color code (without `#` prefix). | +| `hidden` | boolean | Whether the category is hidden from menus. | +| `children` | array | Subcategories (same structure, nested recursively). | +| `media` | array | Image attachments. See [Media object](https://developer.clopos.com/docs/common-objects#media). | +| `created_at` | string | Creation timestamp (ISO 8601). | +| `updated_at` | string | Last update timestamp (ISO 8601). | + +#### Notes + +* With the `type` parameter, you can call different category collections (menu, ingredient, accounting) from a single endpoint. +* By sending `include_children=false`, you can retrieve only top-level categories; sub-branches are retrieved with separate calls. +* The `depth` field indicates the hierarchy level: `0` for root categories, `1` for first-level children, and so on. +* To see inactive categories, send `include_inactive=true`; otherwise, they are hidden by default. +* In a production environment, adjust pagination values (`page`, `limit`) according to the brand's inventory size. + +### Get Category by ID + +Source: + +`GET /v2/categories/{id}` + +Retrieve a specific menu category with its hierarchical details + +#### Purpose + +Returns a single category, regardless of whether it is a root or subcategory, and optionally its child nodes. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/categories/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Request Example + +```bash +curl -X GET "https://integrations.clopos.com/open-api/v2/categories/1?include_children=true" \ + -H "x-token: oauth_example_token" \ +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/categories/1?include_children=true', { + headers: { + 'x-token': 'oauth_example_token', + } +}); + +const category = await response.json(); +``` + +```python +import requests + +url = "https://integrations.clopos.com/open-api/v2/categories/1" +headers = { + "x-token": "oauth_example_token", +} +params = { + "include_children": True +} + +response = requests.get(url, headers=headers, params=params) +category = response.json() +``` + +#### Response + +##### 200 OK — Category found + +```json +{ + "success": true, + "data": { + "id": 1, + "name": "Pizza", + "status": 1, + "hidden": false, + "type": "PRODUCT", + "position": null, + "parent_id": null, + "depth": 0, + "color": "00bcd4", + "children": [], + "media": [ + { + "uuid": "1d76f22b-c209-4fac-be3a-cfde7b8f0d74", + "mime_type": "image/jpeg", + "size": 87281, + "urls": { + "original": "https://cdn.clopos.com/omega/1d76f22b-.../original.jpg", + "extra_large": "https://cdn.clopos.com/omega/1d76f22b-.../extra_large.jpg", + "thumb": "https://cdn.clopos.com/omega/1d76f22b-.../thumb.jpg" + }, + "blur_hash": "LEIpFsE%t1}TxpENEgaK0iowRktQ", + "dimensions": { + "width": 612, + "height": 459 + } + } + ], + "created_at": "2026-01-28T18:23:53.000000Z", + "updated_at": "2026-01-28T18:23:53.000000Z" + } +} +``` + +##### 404 Not Found — Category does not exist + +```json +{ + "success": false, + "error": "resource_not_found", + "message": "Category not found" +} +``` + +#### Field Reference + +##### Category Object + +| Field | Type | Description | +| ------------ | ------------------ | -------------------------------------------------------------------------------------------------------------- | +| `id` | integer | Unique identifier. | +| `name` | string | Category name. | +| `status` | integer | `1` = active, `0` = inactive. | +| `type` | string | `PRODUCT`, `INGREDIENT`, or `ACCOUNTING`. | +| `position` | integer (nullable) | Display order position. | +| `parent_id` | integer (nullable) | Parent category ID, `null` for root categories. | +| `_lft` | integer | Left boundary in the nested-set tree. Useful for ordering and subtree queries. | +| `_rgt` | integer | Right boundary in the nested-set tree. A category's descendants have `_lft` and `_rgt` values between its own. | +| `depth` | integer | Hierarchy level (`0` = root). | +| `color` | string | HEX color code (without `#` prefix). | +| `hidden` | boolean | Whether the category is hidden from menus. | +| `children` | array | Subcategories (same structure, nested recursively). | +| `media` | array | Image attachments. See [Media object](https://developer.clopos.com/docs/common-objects#media). | +| `created_at` | string | Creation timestamp (ISO 8601). | +| `updated_at` | string | Last update timestamp (ISO 8601). | + +#### Notes + +* The `include_children=false` parameter returns only a single category record; recommended for performance in large trees. +* The returned `children` array recursively uses the same schema; be careful when processing the tree structure repeatedly on the client side. +* Based on the `type` field in the response, you can read menu, ingredient, or accounting categories from the same endpoint. +* If the category is not found, it returns `404`; add fallback or remapping logic on the client side. + +## Customers + +### Create Customer + +Source: + +`POST /v2/customers` + +Create a new customer with contact information and group assignment + +#### Purpose + +Create a new customer in the Clopos system. This endpoint allows you to register customers with their contact information, assign them to customer groups, and set up their profile details. + +#### HTTP Request + +```http +POST https://integrations.clopos.com/open-api/v2/customers +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +!!! note + The fields `code`, `phone`, and `cid` are unique. If you attempt to create a customer with duplicate values for any of these fields, the API will return an error. + +#### Request Body + +- `` (string): Customer's full name. This field is required. + +- `` (string): Customer's email address. + +- `` (string): Customer's primary phone number. Must be unique across all customers. + +- `` (string): Customer code/identifier. Must be unique across all customers. + +- `` (string): Customer UUID identifier. Must be unique across all customers. If not provided, the system will generate one automatically. + +- `` (string): Additional notes or description about the customer. + +- `` (integer): ID of the customer group to assign this customer to. + +- `` (integer): Customer's gender. Use `1` for male, `2` for female, or `null` for unspecified. + +- `` (string): Customer's date of birth in `YYYY-MM-DD` format. + +#### Request Examples + +```bash +curl --location 'https://integrations.clopos.com/open-api/v2/customers' \ + --header 'accept: application/json, text/plain, */*' \ + --header 'x-token: oauth_example_token' \ + --header 'content-type: application/json' \ + --data-raw '{ + "name": "John Doe", + "email": "john.doe@example.com", + "code": "CUST001", + "cid": "0f9654bc-9520-43d7-8109-317d9820f54c", + "phone": "+15551234567", + "description": "Test Customer", + "group_id": 1, + "gender": 1, + "date_of_birth": "1990-05-15" +}' +``` + +```javascript +const customerData = { + name: "John Doe", + email: "john.doe@example.com", + code: "CUST001", + cid: "0f9654bc-9520-43d7-8109-317d9820f54c", + phone: "+15551234567", + description: "Test Customer", + group_id: 1, + gender: 1, + date_of_birth: "1990-05-15" +}; + +const response = await fetch('https://integrations.clopos.com/open-api/v2/customers', { + method: 'POST', + headers: { + 'x-token': 'oauth_example_token', + 'Content-Type': 'application/json' + }, + body: JSON.stringify(customerData) +}); + +const customer = await response.json(); +``` + +```python +import requests + +url = "https://integrations.clopos.com/open-api/v2/customers" +headers = { + "x-token": "oauth_example_token", + "Content-Type": "application/json" +} + +customer_data = { + "name": "John Doe", + "email": "john.doe@example.com", + "code": "CUST001", + "cid": "0f9654bc-9520-43d7-8109-317d9820f54c", + "phone": "+15551234567", + "description": "Test Customer", + "group_id": 1, + "gender": 1, + "date_of_birth": "1990-05-15" +} + +response = requests.post(url, headers=headers, json=customer_data) +customer = response.json() +``` + +#### Response + +##### 200 OK — Customer created successfully + +```json +{ + "success": true, + "data": { + "id": 14, + "venue_id": 1, + "cid": "0f9654bc-9520-43d7-8109-317d9820f54c", + "group_id": 1, + "name": "John Doe", + "email": "john.doe@example.com", + "phone": "+15551234567", + "phones": [], + "address": null, + "address_data": [], + "description": "Test Customer", + "discount": 0, + "spent": 0, + "total_discount": 0, + "total_bonus": 0, + "receipt_count": 0, + "gender": 1, + "date_of_birth": "1990-05-15", + "code": "CUST001", + "source": null, + "reference_id": null, + "status": true, + "can_use_loyalty_system": false, + "is_verified": false, + "created_at": "2025-11-14T08:31:17.000000Z", + "updated_at": "2025-11-14T08:31:17.000000Z" + } +} +``` + +##### 400 Bad Request — Validation error + +```json +{ + "success": false, + "message": "Validation failed", + "error": "The name field is required." +} +``` + +##### 409 Conflict — Duplicate unique field + +```json +{ + "success": false, + "message": "Customer with this phone number already exists", + "error": "duplicate_phone" +} +``` + +#### Field Reference + +##### Required Fields + +| Field | Type | Description | +| ------ | ------ | --------------------- | +| `name` | string | Customer's full name. | + +##### Optional Fields + +| Field | Type | Description | +| --------------- | ------- | -------------------------------------------------------------- | +| `email` | string | Customer's email address. | +| `phone` | string | Primary phone number. Must be unique. | +| `code` | string | Customer code/identifier. Must be unique. | +| `cid` | string | Customer UUID. Must be unique. Auto-generated if not provided. | +| `description` | string | Additional notes about the customer. | +| `group_id` | integer | ID of the customer group. | +| `gender` | integer | Gender: `1` = male, `2` = female, `null` = unspecified. | +| `date_of_birth` | string | Date of birth in `YYYY-MM-DD` format. | + +##### Response Fields + +| Field | Type | Description | +| ------------------------ | ------- | ------------------------------------------------ | +| `id` | integer | Unique customer identifier (auto-assigned). | +| `venue_id` | integer | Venue the customer was created in. | +| `cid` | string | UUID identifier for the customer. | +| `status` | boolean | Account status (defaults to `true`). | +| `can_use_loyalty_system` | boolean | Loyalty enrollment status (defaults to `false`). | +| `is_verified` | boolean | Verification status (defaults to `false`). | +| `created_at` | string | Creation timestamp (ISO 8601). | +| `updated_at` | string | Last update timestamp (ISO 8601). | + +#### Notes + +* The `name` field is required and cannot be empty. +* The fields `code`, `phone`, and `cid` must be unique. Attempting to create a customer with duplicate values will result in a `409 Conflict` error. +* If `cid` is not provided, the system will automatically generate a UUID for the customer. +* The response includes the customer's group information if `group_id` was provided. +* The `can_use_loyalty_system` and `is_verified` fields are set to `false` by default for new customers. + +### List All Customers + +Source: + +`GET /v2/customers` + +Retrieve all customers with pagination, filtering, and relationship inclusion. + +This endpoint retrieves a list of all customers with support for pagination, filtering, and including related data. + +!!! note + There is no `search` parameter on this endpoint. To find customers by name + or phone, use the `filters` parameter described below. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/customers +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Query Parameters + +- `` (integer): Page number for pagination (1-based). + +- `` (integer): Number of customers to return per page (1-999). + +- `` (string): Include related data in the response. Supported values: `group`. You can include multiple `with` parameters. + +- `` (array): + + Filter customers by specific fields. Filters use array notation: + `filters[0][0]=field_name&filters[0][1]=value`. Multiple filters can be + combined using different indices (e.g., `filters[0]`, `filters[1]`). + **Supported filter fields:** - `name`: Filter by customer name (partial + match) - `phones`: Filter by phone number (searches in all phone numbers) - + `group_id`: Filter by customer group ID **Filter Examples:** - Filter by + name: `filters[0][0]=name&filters[0][1]=John` - Filter by phone: + `filters[0][0]=phones&filters[0][1]=15551234567` - Multiple filters: + `filters[0][0]=name&filters[0][1]=John&filters[1][0]=phones&filters[1][1]=15551234567` + +#### Request Examples + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/customers?page=1&limit=50" \ + -H "x-token: oauth_example_token" \ +``` + +```bash +curl --location --globoff 'https://integrations.clopos.com/open-api/v2/customers?page=1&limit=50&with[0]=group&filters[0][0]=name&filters[0][1]=John&filters[1][0]=phones&filters[1][1]=15551234567' \ + -H "x-token: oauth_example_token" \ +``` + +```javascript +// Basic request +const params = new URLSearchParams({ + page: "1", + limit: "50", +}); + +// With filters and relations +const paramsWithFilters = new URLSearchParams({ + page: "1", + limit: "50", + "with[0]": "group", + "filters[0][0]": "name", + "filters[0][1]": "John", + "filters[1][0]": "phones", + "filters[1][1]": "15551234567", +}); + +const response = await fetch( + `https://integrations.clopos.com/open-api/v2/customers?${paramsWithFilters}`, + { + headers: { + "x-token": "oauth_example_token", + }, + }, +); + +const customers = await response.json(); +``` + +```python +import requests + +url = "https://integrations.clopos.com/open-api/v2/customers" +headers = { + "x-token": "oauth_example_token", +} + +# Basic request +params = { + "page": 1, + "limit": 50 +} + +# With filters and relations +params_with_filters = { + "page": 1, + "limit": 50, + "with[0]": "group", + "filters[0][0]": "name", + "filters[0][1]": "John", + "filters[1][0]": "phones", + "filters[1][1]": "15551234567" +} + +response = requests.get(url, headers=headers, params=params_with_filters) +customers = response.json() +``` + +#### Response Example + +```json +{ + "success": true, + "data": [ + { + "id": 1, + "venue_id": 1, + "cid": "1266eb42-9bdb-4e93-9fe0-3603c110f128", + "group_id": 5, + "name": "Rahid Akhundzada", + "discount": 0, + "email": null, + "phones": [], + "phone": "+994505355757", + "address": null, + "description": null, + "address_data": [], + "spent": 1162.8, + "total_discount": 1.7, + "total_bonus": 0, + "receipt_count": 9, + "gender": 1, + "date_of_birth": null, + "code": null, + "source": null, + "reference_id": null, + "status": true, + "can_use_loyalty_system": false, + "is_verified": false, + "created_at": "2026-01-31T16:23:27.000000Z", + "updated_at": "2026-03-12T16:37:15.000000Z" + }, + { + "id": 2, + "venue_id": 1, + "cid": "24d7865f-f1bc-4948-be6a-e497d20bad0c", + "group_id": 1, + "name": "Reyal", + "discount": 0, + "email": null, + "phones": [], + "phone": null, + "address": null, + "description": null, + "address_data": [], + "spent": 714, + "total_discount": 0, + "total_bonus": 0, + "receipt_count": 10, + "gender": null, + "date_of_birth": null, + "code": null, + "source": null, + "reference_id": null, + "status": true, + "can_use_loyalty_system": false, + "is_verified": false, + "created_at": "2026-02-02T19:45:10.000000Z", + "updated_at": "2026-02-02T23:37:33.000000Z" + } + ], + "total": 7 +} +``` + +#### Field Reference + +##### Customer Object + +| Field | Type | Description | +| ------------------------ | ------------------ | -------------------------------------------------------------------- | +| `id` | integer | Unique customer identifier. | +| `cid` | string | UUID identifier for the customer. | +| `venue_id` | integer | The venue this customer belongs to. | +| `group_id` | integer | The ID of the customer group they belong to. | +| `name` | string | Customer's full name. | +| `email` | string (nullable) | Customer's email address. | +| `phone` | string (nullable) | Primary phone number. | +| `phones` | array | Additional phone numbers. | +| `address` | string (nullable) | Customer's address. | +| `address_data` | array | Structured address entries with type, source, and formatted address. | +| `description` | string (nullable) | Additional notes about the customer. | +| `discount` | number | Customer-level discount value. | +| `spent` | number | Total amount spent by the customer. | +| `total_discount` | number | Total discount amount received across all receipts. | +| `total_bonus` | number | Total bonus amount used. | +| `receipt_count` | integer | Total number of receipts for the customer. | +| `gender` | integer (nullable) | Gender: `1` = male, `2` = female, `null` = unspecified. | +| `date_of_birth` | string (nullable) | Date of birth in `YYYY-MM-DD` format. | +| `code` | string (nullable) | Customer code/identifier. | +| `source` | string (nullable) | Where the customer was created from (e.g., `LOYALTY`). | +| `reference_id` | string (nullable) | External reference ID for third-party integrations. | +| `status` | boolean | Whether the customer account is active. | +| `can_use_loyalty_system` | boolean | Whether the customer is enrolled in the loyalty system. | +| `is_verified` | boolean | Whether the customer's identity has been verified. | +| `created_at` | string | Timestamp when the customer was created (ISO 8601). | +| `updated_at` | string | Timestamp when the customer was last updated (ISO 8601). | + +#### Notes + +* **Filterable fields:** `name` (partial match), `phones` (searches across all phone numbers), `group_id` (exact match). Note: use `phones` (plural) — the singular `phone` field is not filterable. +* **Sortable fields:** `id`, `cid`, `group_id`, `name`, `email`, `address`, `created_at`, `updated_at`. +* The `search` query parameter is listed in some older references but is **not implemented** — use `filters` instead. + +### Get Customer by ID + +Source: + +`GET /v2/customers/{id}` + +Retrieve a specific customer by their unique identifier. + +This endpoint retrieves a specific customer by their unique ID. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/customers/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +- `` (integer): The unique identifier of the customer to retrieve. + +#### Request Example + +```bash +curl --location 'https://integrations.clopos.com/open-api/v2/customers/1' \ + -H "x-token: oauth_example_token" \ +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/customers/1', { + headers: { + 'x-token': 'oauth_example_token', + } +}); + +const customer = await response.json(); +``` + +```python +import requests + +url = "https://integrations.clopos.com/open-api/v2/customers/1" +headers = { + "x-token": "oauth_example_token", +} + +response = requests.get(url, headers=headers) +customer = response.json() +``` + +#### Response + +```json +{ + "success": true, + "data": { + "id": 1, + "venue_id": 1, + "cid": "1266eb42-9bdb-4e93-9fe0-3603c110f128", + "group_id": 5, + "name": "Rahid Akhundzada", + "discount": 0, + "email": null, + "phones": [], + "phone": "+994505355757", + "address": null, + "description": null, + "address_data": [], + "spent": 1162.8, + "total_discount": 1.7, + "total_bonus": 0, + "receipt_count": 9, + "gender": 1, + "date_of_birth": null, + "code": null, + "source": null, + "reference_id": null, + "status": true, + "can_use_loyalty_system": false, + "is_verified": false, + "created_at": "2026-01-31T16:23:27.000000Z", + "updated_at": "2026-03-12T16:37:15.000000Z" + } +} +``` + +#### Field Reference + +##### Customer Object + +| Field | Type | Description | +| ------------------------ | ------------------ | -------------------------------------------------------------------- | +| `id` | integer | Unique customer identifier. | +| `cid` | string | UUID identifier for the customer. | +| `venue_id` | integer | The venue this customer belongs to. | +| `group_id` | integer | The ID of the customer group they belong to. | +| `name` | string | Customer's full name. | +| `email` | string (nullable) | Customer's email address. | +| `phone` | string (nullable) | Primary phone number. | +| `phones` | array | Additional phone numbers. | +| `address` | string (nullable) | Customer's address. | +| `address_data` | array | Structured address entries with type, source, and formatted address. | +| `description` | string (nullable) | Additional notes about the customer. | +| `discount` | number | Customer-level discount value. | +| `spent` | number | Total amount spent by the customer. | +| `total_discount` | number | Total discount amount received across all receipts. | +| `total_bonus` | number | Total bonus amount used. | +| `receipt_count` | integer | Total number of receipts for the customer. | +| `gender` | integer (nullable) | Gender: `1` = male, `2` = female, `null` = unspecified. | +| `date_of_birth` | string (nullable) | Date of birth in `YYYY-MM-DD` format. | +| `code` | string (nullable) | Customer code/identifier. | +| `source` | string (nullable) | Where the customer was created from (e.g., `LOYALTY`). | +| `reference_id` | string (nullable) | External reference ID for third-party integrations. | +| `status` | boolean | Whether the customer account is active. | +| `can_use_loyalty_system` | boolean | Whether the customer is enrolled in the loyalty system. | +| `is_verified` | boolean | Whether the customer's identity has been verified. | +| `created_at` | string | Timestamp when the customer was created (ISO 8601). | +| `updated_at` | string | Timestamp when the customer was last updated (ISO 8601). | + +### List Customer Groups + +Source: + +`GET /v2/customer-groups` + +Retrieve a list of all customer groups with pagination support. + +This endpoint retrieves a list of all customer groups. + +```json +{ + "success": true, + "data": [ + { + "id": 1, + "name": "My Customers", + "discount_type": null, + "discount_value": 0, + "system_type": "my_customers", + "created_at": "2025-08-16T15:21:15.000000Z", + "updated_at": "2025-08-16T15:21:15.000000Z", + "deleted_at": null + } + ], + "total": 1, + "time": 71, + "timestamp": "2025-10-24 05:38:15", + "sorts": [ + "id", + "name", + "discount_type", + "discount_value", + "total_amount", + "created_at", + "updated_at", + "deleted_at" + ], + "unix": 1761284295 +} +``` + +##### Customer Group Object + +| Field | Type | Description | +| ---------------- | -------------- | ----------------------------------------------------- | +| `id` | integer | The unique identifier for the customer group. | +| `name` | string | The name of the customer group. | +| `discount_type` | string \| null | The type of discount associated with the group. | +| `discount_value` | number | The value of the discount. | +| `system_type` | string \| null | The system type of the group (e.g., 'my\_customers'). | +| `created_at` | string | The timestamp when the group was created. | + +## Finance + +### Get Balance by ID + +Source: + +`GET /v2/finance/balances/{id}` + +Retrieve a single account. + +Fetch one account by its identifier. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/finance/balances/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ----------------------- | +| Integrator scope | `finance-balances:read` | +| User ability | `FINANCE_BALANCE_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/finance/balances/1" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/finance/balances/1', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/finance/balances/1", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### Balance Date States + +Source: + +`GET /v2/finance/balances/date-states` + +Per-date balance states. + +Balance state per date across the requested range. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/finance/balances/date-states +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ----------------------- | +| Integrator scope | `finance-balances:read` | +| User ability | `FINANCE_BALANCE_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/finance/balances/date-states" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/finance/balances/date-states', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/finance/balances/date-states", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### Balance Transactions + +Source: + +`GET /v2/finance/balances/transactions` + +Transactions grouped by account. + +Transactions viewed per account. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/finance/balances/transactions +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ----------------------- | +| Integrator scope | `finance-balances:read` | +| User ability | `FINANCE_BALANCE_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/finance/balances/transactions" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/finance/balances/transactions', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/finance/balances/transactions", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +#### Notes + +* Proxies to client-api `finance/balance/transaction`. + +### List Balances + +Source: + +`GET /v2/finance/balances` + +Cash and bank accounts. + +Accounts money is held in, each with its current `amount`. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/finance/balances +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ----------------------- | +| Integrator scope | `finance-balances:read` | +| User ability | `FINANCE_BALANCE_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/finance/balances" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/finance/balances', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/finance/balances", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### Balance List + +Source: + +`GET /v2/finance/balances/list` + +Condensed account list. + +A lighter account list intended for selectors. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/finance/balances/list +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ----------------------- | +| Integrator scope | `finance-balances:read` | +| User ability | `FINANCE_BALANCE_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/finance/balances/list" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/finance/balances/list', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/finance/balances/list", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### Get Cash Shift by ID + +Source: + +`GET /v2/finance/cash-shifts/{id}` + +Retrieve a single shift. + +Fetch one cash shift. **The identifier is a UUID, not an integer.** + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/finance/cash-shifts/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | -------------------------- | +| Integrator scope | `finance-cash-shifts:read` | +| User ability | `CASH_SHIFT_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/finance/cash-shifts/9c1e7a30-4b2f-4d18-9f6a-71c0d8e4b5a2" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/finance/cash-shifts/9c1e7a30-4b2f-4d18-9f6a-71c0d8e4b5a2', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/finance/cash-shifts/9c1e7a30-4b2f-4d18-9f6a-71c0d8e4b5a2", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +#### Notes + +* Cash shifts are the one resource in v2 keyed by a UUID; passing an integer returns `400`. + +### Cash Shift Report + +Source: + +`GET /v2/finance/cash-shifts/{id}/report` + +Totals for one shift. + +Sales, refunds and cash in/out totals for a single shift. The identifier is a UUID. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/finance/cash-shifts/{id}/report +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | -------------------------- | +| Integrator scope | `finance-cash-shifts:read` | +| User ability | `CASH_SHIFT_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/finance/cash-shifts/9c1e7a30-4b2f-4d18-9f6a-71c0d8e4b5a2/report" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/finance/cash-shifts/9c1e7a30-4b2f-4d18-9f6a-71c0d8e4b5a2/report', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/finance/cash-shifts/9c1e7a30-4b2f-4d18-9f6a-71c0d8e4b5a2/report", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### List Cash Shifts + +Source: + +`GET /v2/finance/cash-shifts` + +Till sessions. + +Till sessions opened and closed on terminals. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/finance/cash-shifts +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | -------------------------- | +| Integrator scope | `finance-cash-shifts:read` | +| User ability | `CASH_SHIFT_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/finance/cash-shifts" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/finance/cash-shifts', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/finance/cash-shifts", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +#### Notes + +* Requires the Cash Shift module; without it the endpoint answers `403`. + +### Customer Balances + +Source: + +`GET /v2/finance/balances/customer` + +Balances held against customers. + +Outstanding balances per customer. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/finance/balances/customer +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ----------------------- | +| Integrator scope | `finance-balances:read` | +| User ability | `FINANCE_BALANCE_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/finance/balances/customer" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/finance/balances/customer', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/finance/balances/customer", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### List Finance Categories + +Source: + +`GET /v2/finance/categories` + +Categories money movements are classified under. + +The categories transactions are filed under. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/finance/categories +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ------------------------- | +| Integrator scope | `finance-categories:read` | +| User ability | `FINANCE_CATEGORY_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/finance/categories" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/finance/categories', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/finance/categories", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### Get Finance Category by ID + +Source: + +`GET /v2/finance/categories/{id}` + +Retrieve a single category. + +Fetch one finance category by its identifier. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/finance/categories/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ------------------------- | +| Integrator scope | `finance-categories:read` | +| User ability | `FINANCE_CATEGORY_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/finance/categories/1" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/finance/categories/1', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/finance/categories/1", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### Get Tax by ID + +Source: + +`GET /v2/finance/taxes/{id}` + +Retrieve a single tax rate. + +Fetch one tax rate by its identifier. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/finance/taxes/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | -------------------- | +| Integrator scope | `finance-taxes:read` | +| User ability | `TAX_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/finance/taxes/1" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/finance/taxes/1', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/finance/taxes/1", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### Tax Report + +Source: + +`GET /v2/finance/taxes/report` + +Tax report over a period. + +Tax report across the requested period. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/finance/taxes/report +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | -------------------- | +| Integrator scope | `finance-taxes:read` | +| User ability | `TAX_REPORT_SHOW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/finance/taxes/report" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/finance/taxes/report', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/finance/taxes/report", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +#### Notes + +* Proxies to client-api `finance/tax/report`. Requires `TAX_REPORT_SHOW`, not `TAX_VIEW`. + +### Tax Totals + +Source: + +`GET /v2/finance/taxes/total` + +Aggregate tax amounts. + +Aggregate tax amounts for the current filters. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/finance/taxes/total +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | -------------------- | +| Integrator scope | `finance-taxes:read` | +| User ability | `TAX_REPORT_SHOW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/finance/taxes/total" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/finance/taxes/total', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/finance/taxes/total", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +#### Notes + +* Proxies to client-api `finance/tax/total`. Requires `TAX_REPORT_SHOW`. + +### Tax Types + +Source: + +`GET /v2/finance/taxes/types` + +The tax type vocabulary. + +Returns the tax type list, so you do not have to hard-code it. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/finance/taxes/types +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | -------------------- | +| Integrator scope | `finance-taxes:read` | +| User ability | `TAX_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/finance/taxes/types" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/finance/taxes/types', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/finance/taxes/types", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +#### Notes + +* Proxies to client-api `finance/tax/types`. + +### List Taxes + +Source: + +`GET /v2/finance/taxes` + +Configured tax rates. + +Tax rates configured for the brand. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/finance/taxes +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | -------------------- | +| Integrator scope | `finance-taxes:read` | +| User ability | `TAX_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/finance/taxes" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/finance/taxes', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/finance/taxes", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### Get Transaction by ID + +Source: + +`GET /v2/finance/transactions/{id}` + +Retrieve a single transaction. + +Fetch one transaction by its identifier. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/finance/transactions/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | --------------------------- | +| Integrator scope | `finance-transactions:read` | +| User ability | `FINANCE_TRANSACTION_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/finance/transactions/1" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/finance/transactions/1', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/finance/transactions/1", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### List Transactions + +Source: + +`GET /v2/finance/transactions` + +Money movements. + +Money in and out. `before_amount`/`after_amount` bracket each movement against `balance_id`. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/finance/transactions +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | --------------------------- | +| Integrator scope | `finance-transactions:read` | +| User ability | `FINANCE_TRANSACTION_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/finance/transactions" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/finance/transactions', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/finance/transactions", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +#### Notes + +* Transactions link back to whatever caused them: `receipt_id`, `operation_id`, `customer_id` or `supplier_id`. + +## Inventory + +### Get Operation by ID + +Source: + +`GET /v2/operations/{id}` + +Retrieve a single document. + +Fetch one inventory document by its identifier. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/operations/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ----------------- | +| Integrator scope | `operations:read` | +| User ability | `STOCK_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/operations/1" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/operations/1', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/operations/1", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### Get Operation Items + +Source: + +`GET /v2/operations/{id}/items` + +Line items of one document. + +The line items belonging to a single operation. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/operations/{id}/items +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ----------------- | +| Integrator scope | `operations:read` | +| User ability | `STOCK_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/operations/1/items" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/operations/1/items', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/operations/1/items", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### Operation Statuses + +Source: + +`GET /v2/operations/statuses` + +The status vocabulary. + +Returns the status list with localised display names, so you do not have to hard-code them. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/operations/statuses +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ----------------- | +| Integrator scope | `operations:read` | +| User ability | `STOCK_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/operations/statuses" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/operations/statuses', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/operations/statuses", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### List Operations + +Source: + +`GET /v2/operations` + +Inventory documents. + +The documents that move stock: supply, waste, transfer, production and inventory checks. `type` says which; see the table below. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/operations +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ----------------- | +| Integrator scope | `operations:read` | +| User ability | `STOCK_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/operations" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/operations', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/operations", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +#### Operation Types + +| `type` | Meaning | +| ------ | ----------------- | +| `1` | IN — supply | +| `3` | TRANSFER | +| `4` | WASTE | +| `5` | RETURN | +| `7` | MAKE — production | +| `9` | INVENTORY\_CHECK | +| `10` | SUPPLY\_RETURN | +| `11` | INITIAL\_STOCK | + +`2` (OUT), `6` (FIXATION) and `8` (MERGE) are deprecated and only appear on historical records. + +`status` is `1` (Published) or `2` (Draft). + +### Operation Totals + +Source: + +`GET /v2/operations/total` + +Aggregate subtotal. + +Aggregate over the same filters as the list endpoint. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/operations/total +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ----------------- | +| Integrator scope | `operations:read` | +| User ability | `STOCK_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/operations/total" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/operations/total', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/operations/total", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### List Stock + +Source: + +`GET /v2/stock` + +Current stock levels per product and storage. + +Read what is currently on hand. Each row is a product in one storage, with `quantity` on hand and `reserved` held by open receipts. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/stock +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ------------ | +| Integrator scope | `stock:read` | +| User ability | `STOCK_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/stock" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/stock', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/stock", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +#### Notes + +* Use `/v2/stock/total` for the aggregate, and `/v2/storages` to resolve `storage_id`. + +### Get Stock by ID + +Source: + +`GET /v2/stock/{id}` + +Retrieve a single stock row. + +Fetch one stock row by its identifier. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/stock/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ------------ | +| Integrator scope | `stock:read` | +| User ability | `STOCK_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/stock/1" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/stock/1', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/stock/1", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### Stock by Product + +Source: + +`GET /v2/stock/product` + +Stock resolved per product. + +Same data as `/v2/stock`, collapsed to one row per product instead of one per storage row. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/stock/product +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ------------ | +| Integrator scope | `stock:read` | +| User ability | `STOCK_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/stock/product" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/stock/product', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/stock/product", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### Stock by Product Group + +Source: + +`GET /v2/stock/product-group` + +Stock aggregated by product group. + +Stock rolled up to product groups. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/stock/product-group +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ------------ | +| Integrator scope | `stock:read` | +| User ability | `STOCK_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/stock/product-group" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/stock/product-group', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/stock/product-group", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +#### Notes + +* Proxies to client-api `stock/productGroup`; the gateway exposes the hyphenated form. + +### Stock Info + +Source: + +`GET /v2/stock/info` + +Summary information about stock across storages. + +Summary counters used by the stock dashboard. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/stock/info +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ------------ | +| Integrator scope | `stock:read` | +| User ability | `STOCK_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/stock/info" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/stock/info', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/stock/info", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### Get Stock Operation by ID + +Source: + +`GET /v2/stock-operations/{id}` + +Retrieve a single movement. + +Fetch one stock movement by its identifier. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/stock-operations/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ----------------------- | +| Integrator scope | `stock-operations:read` | +| User ability | `STOCK_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/stock-operations/1" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/stock-operations/1', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/stock-operations/1", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### List Stock Operations + +Source: + +`GET /v2/stock-operations` + +Every stock movement. + +The movement ledger: supplies, waste, transfers, production and the deductions receipts cause. `before_quantity`/`after_quantity` bracket each movement. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/stock-operations +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ----------------------- | +| Integrator scope | `stock-operations:read` | +| User ability | `STOCK_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/stock-operations" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/stock-operations', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/stock-operations", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +#### Notes + +* Rows caused by a receipt carry `receipt_id` and `receipt_product_id`; rows caused by an inventory document carry `operation_id`. + +### Stock Operations by Product + +Source: + +`GET /v2/stock-operations/products` + +Per-product movement view. + +Movement grouped per product rather than per row. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/stock-operations/products +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ----------------------- | +| Integrator scope | `stock-operations:read` | +| User ability | `STOCK_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/stock-operations/products" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/stock-operations/products', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/stock-operations/products", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +#### Notes + +* Proxies to client-api `stock-operations/follow/products`. + +### Stock Operation Totals + +Source: + +`GET /v2/stock-operations/total` + +Aggregate quantity and cost. + +Aggregate over the same filters as the list endpoint. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/stock-operations/total +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ----------------------- | +| Integrator scope | `stock-operations:read` | +| User ability | `STOCK_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/stock-operations/total" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/stock-operations/total', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/stock-operations/total", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### Stock Totals + +Source: + +`GET /v2/stock/total` + +Aggregate stock value and quantity. + +Aggregate of the same rows `/v2/stock` returns, honouring the same filters. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/stock/total +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ------------ | +| Integrator scope | `stock:read` | +| User ability | `STOCK_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/stock/total" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/stock/total', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/stock/total", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### Get Storage by ID + +Source: + +`GET /v2/storages/{id}` + +Retrieve a single storage. + +Fetch one storage by its identifier. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/storages/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | -------------------- | +| Integrator scope | `storages:read` | +| User ability | `STOCK_STORAGE_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/storages/1" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/storages/1', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/storages/1", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### List Storages + +Source: + +`GET /v2/storages` + +Storage locations. + +The storages stock is tracked against. Needed to make sense of `storage_id` on stock rows and operations. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/storages +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | -------------------- | +| Integrator scope | `storages:read` | +| User ability | `STOCK_STORAGE_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/storages" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/storages', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/storages", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### Get Supplier by ID + +Source: + +`GET /v2/suppliers/{id}` + +Retrieve a single supplier. + +Fetch one supplier by its identifier. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/suppliers/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | --------------------- | +| Integrator scope | `suppliers:read` | +| User ability | `STOCK_SUPPLIER_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/suppliers/1" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/suppliers/1', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/suppliers/1", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### List Suppliers + +Source: + +`GET /v2/suppliers` + +Suppliers goods are purchased from. + +Suppliers referenced by supply operations, with `spent` and the linked finance account in `balance_id`. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/suppliers +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | --------------------- | +| Integrator scope | `suppliers:read` | +| User ability | `STOCK_SUPPLIER_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/suppliers" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/suppliers', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/suppliers", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### Supplier Totals + +Source: + +`GET /v2/suppliers/total` + +Aggregate spend and balance. + +Aggregate across suppliers matching the current filters. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/suppliers/total +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | --------------------- | +| Integrator scope | `suppliers:read` | +| User ability | `STOCK_SUPPLIER_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/suppliers/total" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/suppliers/total', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/suppliers/total", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### List Operation Items + +Source: + +`GET /v2/operation-items` + +Line items across documents. + +Operation line items across every document, for reconciliation exports. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/operation-items +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ---------------------- | +| Integrator scope | `operation-items:read` | +| User ability | `STOCK_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/operation-items" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/operation-items', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/operation-items", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +### Operation Item Totals + +Source: + +`GET /v2/operation-items/total` + +Aggregate quantity and cost. + +Aggregate over the same filters as the list endpoint. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/operation-items/total +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | ---------------------- | +| Integrator scope | `operation-items:read` | +| User ability | `STOCK_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/operation-items/total" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/operation-items/total', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/operation-items/total", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +## Orders + +### Create Order (v2) + +Source: + +`POST /v2/orders` + +Submit a POS order using the streamlined v2 schema + +#### Purpose + +Create a new order in Clopos using the simplified v2 payload. Optional fields with defaults can be omitted. + +#### HTTP Request + +```http +POST https://integrations.clopos.com/open-api/v2/orders +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Request Example + +```bash +curl --location 'https://integrations.clopos.com/open-api/v2/orders' \ + --header 'x-token: ' \ + --header 'Content-Type: application/json' \ + --data '{ + "auto_accept_terminal": 1, + "auto_order_accept": true, + "auto_order_sent_to_station": true, + "order_number": "A-1024", + "sale_type_id": 2, + "venue_id": 1, + "delivery_fee": 2.5, + "customer": { + "id": 9, + "phone": "+994705401040", + "address": "123 Main St", + "customer_discount_type": 1, + "name": "Rahid Akhundzada" + }, + "comment": "Leave at the door", + "discount": { + "discount_type": 1, + "discount_value": 10 + }, + "service_charge": { + "enabled": true, + "value": 5 + }, + "products": [ + { + "product_id": 101, + "product_name": "Pizza", + "count": 2, + "price": 8.5, + "status": "new", + "product_hash": "abc123", + "portion_size": 1, + "note": "No onions", + "modifiers": [ + { + "modifier_id": 501, + "modifier_name": "Extra Cheese", + "count": 1, + "price": 0.5, + "portion_size": 1 + } + ] + } + ] + }' +``` + +#### Payload fields + +##### Top-level + +* `auto_accept_terminal` (number, optional): Terminal that auto-accepts. +* `auto_order_accept` (boolean, default `false`): Auto-accept the order. +* `auto_order_sent_to_station` (boolean, default `false`): Auto-send to stations after acceptance. +* `order_number` (string, optional, max 20 chars): Custom order number to assign to the order. +* `sale_type_id` (number, required): Sale type to use. +* `venue_id` (number, required): Venue where the order belongs. +* `delivery_fee` (number, optional): Delivery charge to apply. +* `comment` (string, optional): Free text note for the order. + +##### Discounts + +* `discount` (object, optional; defaults applied if present but fields omitted) + * `discount_type` (number, default `0`) + * `discount_value` (number, default `0`) + +##### Service charge + +* `service_charge` (object, optional; defaults applied if present but fields omitted) + * `enabled` (boolean, default `false`) + * `value` (number, default `0`) + +##### Customer (required) + +* `id` (number) +* `phone` (string) +* `address` (string) +* `customer_discount_type` (number) +* `name` (string) + +##### Products (array, required) + +Each product item requires: + +* `product_id` (number) +* `product_name` (string, required) — Display name of the product +* `count` (number) +* `price` (number) +* `status` (string) +* `product_hash` (string) +* `portion_size` (number, default `1`, optional) +* `note` (string, optional) — Free text note for the product (e.g., "No onions") +* `modifiers` (array, optional; defaults to `[]`) + * `modifier_id` (number) + * `modifier_name` (string, required) — Display name of the modifier + * `count` (number) + * `price` (number, default `0`, optional) + * `portion_size` (number, default `1`, optional) + +!!! info + Optional fields and any values with defaults can be omitted; defaults are + applied server-side . + +##### Response (example) + +```json +{ + "success": true, + "message": "Order created", + "data": { + "id": 295, + "venue_id": 1, + "type": "CALL_CENTER_ORDER", + "integration": "call_center_new", + "integration_uuid": null, + "integration_id": null, + "customer_ref_id": null, + "integration_status": "CREATED", + "status": "PENDING", + "created_at": "2026-01-08T06:28:23.000000Z", + "updated_at": "2026-01-08T06:28:23.000000Z", + "integration_response": null + } +} +``` + +#### Response Field Reference + +| Field | Type | Description | +| ---------------------- | ----------------- | ---------------------------------------------- | +| `id` | integer | Newly created order identifier. | +| `venue_id` | integer | Venue where the order was placed. | +| `type` | string | Order type (e.g., `CALL_CENTER_ORDER`). | +| `integration` | string | Integration channel (e.g., `call_center_new`). | +| `integration_uuid` | string (nullable) | UUID from the integration source, if provided. | +| `integration_id` | string (nullable) | External ID from the integration source. | +| `customer_ref_id` | string (nullable) | External customer reference ID. | +| `integration_status` | string | Initial integration state (`CREATED`). | +| `status` | string | Initial order lifecycle state (`PENDING`). | +| `integration_response` | object (nullable) | Response from the integration, if any. | +| `created_at` | string | Creation timestamp (ISO 8601). | +| `updated_at` | string | Last update timestamp (ISO 8601). | + +### Get Order by ID + +Source: + +`GET /v2/orders/{id}` + +Retrieve a single order with status, customer, and line item details. + +#### Purpose + +Return a specific order so you can inspect its metadata, customer, payment, and fulfillment status without fetching the entire list. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/orders/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Path Parameters + +- `` (string): Unique identifier of the order (numeric ID). + +#### Query Parameters + +- `` (string): + + Include related resources in the response. Currently supported: `receipt:id,service_notification_id,status`. + When included, the `data.receipt` field will be present in the response (or `null` if no receipt exists for the order). + +#### Request Example + +```bash +# Basic request +curl --location "https://integrations.clopos.com/open-api/v2/orders/1" \ + -H "x-token: oauth_example_token" \ + +# Request including receipt (note: --globoff to avoid shell globbing) +curl --location --globoff 'https://integrations.clopos.com/open-api/v2/orders/1?with[0]=receipt%3Aid%2Cservice_notification_id%2Cstatus' \ + -H "x-token: oauth_example_token" \ +``` + +```javascript +// Basic request +const orderId = 1; +let url = `https://integrations.clopos.com/open-api/v2/orders/${orderId}`; + +// Include receipt +const params = new URLSearchParams({ + 'with[0]': 'receipt:id,service_notification_id,status' +}); +const urlWithReceipt = `${url}?${params}`; + +const response = await fetch(urlWithReceipt, { + headers: { + 'x-token': 'oauth_example_token', + } +}); + +const order = await response.json(); +``` + +```python +import requests + +order_id = 1 +base = f"https://integrations.clopos.com/open-api/v2/orders/{order_id}" +params = { + 'with[0]': 'receipt:id,service_notification_id,status' +} +headers = { + "x-token": "oauth_example_token", +} + +response = requests.get(base, headers=headers, params=params) +order = response.json() +``` + +#### Response + +##### 200 OK — Order found + +```json +{ + "success": true, + "data": { + "id": 1, + "venue_id": 1, + "type": "CALL_CENTER_ORDER", + "integration": "call_center_new", + "integration_uuid": null, + "integration_id": null, + "customer_ref_id": null, + "integration_status": "CREATED", + "status": "RECEIVED", + "payload": { + "auto_order_accept": false, + "auto_order_sent_to_station": false, + "delivery_fee": 2.5, + "service": { + "sale_type_id": 2, + "venue_id": 1 + }, + "customer": { + "id": 1, + "phone": "+994705401040", + "address": "123 Main St", + "customer_discount_type": 1, + "name": "Rahid Akhundzada" + }, + "products": [ + { + "product_id": 51, + "count": 2, + "product_modificators": [], + "portion_size": 1, + "meta": { + "price": 8.5, + "order_product": { + "count": 2, + "status": "new", + "product_modificators": [], + "product_hash": "abc123", + "product": { + "id": 51, + "name": "Pizza", + "price": 8.5 + } + } + } + } + ], + "meta": { + "comment": "Leave at the door", + "discount": { + "discount_type": 1, + "discount_value": 10 + }, + "apply_service_charge": true, + "customer_discount_type": 1, + "service_charge_value": 5 + }, + "customer_id": 1, + "sale_type_id": 2 + }, + "created_at": "2026-02-02T13:45:53.000000Z", + "updated_at": "2026-02-02T17:46:02.000000Z", + "integration_response": null + } +} +``` + +##### 404 Not Found — Order does not exist + +```json +{ + "success": false, + "error": "resource_not_found", + "message": "Order not found" +} +``` + +#### Field Reference + +##### Order Object + +| Field | Type | Description | +| ---------------------- | ----------------- | ---------------------------------------------------------------------- | +| `id` | integer | Order identifier. | +| `venue_id` | integer | Venue that owns the order. | +| `type` | string | Source of the order (e.g., `CALL_CENTER_ORDER`). | +| `integration` | string | Integration channel that created the order (e.g., `call_center_new`). | +| `integration_uuid` | string (nullable) | UUID assigned by the integration source. | +| `integration_id` | string (nullable) | External ID from the integration source. | +| `integration_status` | string | State reported by the upstream integration (e.g., `CREATED`). | +| `customer_ref_id` | string (nullable) | External customer reference ID from the integration. | +| `status` | string | Current lifecycle state: `PENDING`, `RECEIVED`, `IGNORE`, `DELIVERED`. | +| `payload` | object | Full order content including service, customer, products, and meta. | +| `payload.service` | object | Sale type and venue for the order. | +| `payload.customer` | object | Customer details (id, phone, address, name). | +| `payload.products` | array | Line items with product\_id, count, modifiers, and pricing meta. | +| `payload.meta` | object | Order-level metadata: comment, discount, service charge settings. | +| `integration_response` | object (nullable) | Response data from the integration, if any. | +| `created_at` | string | Creation timestamp (ISO 8601). | +| `updated_at` | string | Last update timestamp (ISO 8601). | + +#### Notes + +* Returns the same structure as the list endpoint, providing parity between detail and collection responses. +* Use this endpoint after receiving webhook notifications to hydrate UI with complete order data. +* You can embed the linked receipt using the `with[0]` parameter. If the order has no receipt, `receipt` will be `null`. +* Combine with the receipts endpoint when you need final settlement information once the order is delivered. + +### Get Orders + +Source: + +`GET /v2/orders` + +Retrieve orders with replicable filters and status-based searches + +#### Purpose + +Fetches the statuses, customer details, and line items of your multi-channel orders in a single request. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/orders +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Query Parameters + +- `` (integer): Page number for pagination (1-based). + +- `` (integer): Number of orders per page. + +- `` (string): Lifecycle state to filter by. Allowed values: `PENDING`, `RECEIVED`, `IGNORE`, `DELIVERED`. + +- `` (array[string]): Related resources to include in each order. Repeat with indexed brackets (e.g. `with[0]=customer&with[1]=receipt`). + +- `` (string): Start date of a `created_at` range, inclusive. Format: `YYYY-MM-DD`. Pair with `date[1]`. + +- `` (string): End date of a `created_at` range, inclusive. Format: `YYYY-MM-DD`. + +- `` (string): Field to sort by (e.g. `created_at`, `updated_at`, `id`). + +- `` (integer): Sort direction: `1` = ascending, `-1` = descending. + +- `` (array): Additional filter tuples using PHP bracket notation: `filters[N][0]=field_name&filters[N][1]=value`. Stack filters by incrementing `N` (0-based). + +#### Request Example + +```bash +curl -X GET "https://integrations.clopos.com/open-api/v2/orders?limit=20&status=DELIVERED" \ + -H "x-token: oauth_example_token" \ +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/orders?limit=20&status=DELIVERED', { + headers: { + 'x-token': 'oauth_example_token', + } +}); + +const { data } = await response.json(); +``` + +```python +import requests + +url = "https://integrations.clopos.com/open-api/v2/orders" +headers = { + "x-token": "oauth_example_token", +} +params = { + "limit": 20, + "status": "DELIVERED" +} + +response = requests.get(url, headers=headers, params=params) +orders = response.json() +``` + +#### Response + +##### 200 OK — Orders list + +```json +{ + "success": true, + "data": [ + { + "id": 1, + "venue_id": 1, + "type": "CALL_CENTER_ORDER", + "integration": "call_center_new", + "integration_uuid": null, + "integration_id": null, + "customer_ref_id": null, + "integration_status": "CREATED", + "status": "RECEIVED", + "payload": { + "auto_order_accept": false, + "auto_order_sent_to_station": false, + "delivery_fee": 2.5, + "service": { + "sale_type_id": 2, + "venue_id": 1 + }, + "customer": { + "id": 1, + "phone": "+994705401040", + "address": "123 Main St", + "customer_discount_type": 1, + "name": "Rahid Akhundzada" + }, + "products": [ + { + "product_id": 51, + "count": 2, + "product_modificators": [], + "portion_size": 1, + "meta": { + "price": 8.5, + "order_product": { + "count": 2, + "status": "new", + "product_modificators": [], + "product_hash": "abc123", + "product": { + "id": 51, + "name": "Pizza", + "price": 8.5 + } + } + } + } + ], + "meta": { + "comment": "Leave at the door", + "discount": { + "discount_type": 1, + "discount_value": 10 + }, + "apply_service_charge": true, + "customer_discount_type": 1, + "service_charge_value": 5 + }, + "customer_id": 1, + "sale_type_id": 2 + }, + "created_at": "2026-02-02T13:45:53.000000Z", + "updated_at": "2026-02-02T17:46:02.000000Z", + "integration_response": null + } + ], + "total": 4 +} +``` + +##### 401 Unauthorized — Authentication is missing or invalid + +```json +{ + "success": false, + "error": "unauthorized", + "message": "Missing or invalid authentication headers" +} +``` + +#### Field Reference + +##### Order Object + +| Field | Type | Description | +| ---------------------- | ----------------- | ---------------------------------------------------------------------- | +| `id` | integer | Order identifier. | +| `venue_id` | integer | Venue that owns the order. | +| `type` | string | Source of the order (e.g., `CALL_CENTER_ORDER`). | +| `integration` | string | Integration channel that created the order (e.g., `call_center_new`). | +| `integration_uuid` | string (nullable) | UUID assigned by the integration source. | +| `integration_id` | string (nullable) | External ID from the integration source. | +| `integration_status` | string | State reported by the upstream integration (e.g., `CREATED`). | +| `customer_ref_id` | string (nullable) | External customer reference ID from the integration. | +| `status` | string | Current lifecycle state: `PENDING`, `RECEIVED`, `IGNORE`, `DELIVERED`. | +| `payload` | object | Full order content including service, customer, products, and meta. | +| `payload.service` | object | Sale type and venue for the order. | +| `payload.customer` | object | Customer details (id, phone, address, name). | +| `payload.products` | array | Line items with product\_id, count, modifiers, and pricing meta. | +| `payload.meta` | object | Order-level metadata: comment, discount, service charge settings. | +| `integration_response` | object (nullable) | Response data from the integration, if any. | +| `created_at` | string | Creation timestamp (ISO 8601). | +| `updated_at` | string | Last update timestamp (ISO 8601). | + +#### Notes + +* When an order is created through this endpoint, the POS receives a push notification and notifies the clerk of the new order. `RECEIVED` orders automatically transition into open receipts. +* Use `status=PENDING` to monitor orders awaiting POS confirmation. +* Poll or subscribe to webhooks to track further status changes if your integration requires real-time updates. + +### Update Order + +Source: + +`PUT /v2/orders/{id}` + +Update the status of an existing order + +#### Purpose + +Send a simple status update to mark an order as ignored. + +#### HTTP Request + +```http +PUT https://integrations.clopos.com/open-api/v2/orders/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Path Parameters + +- `` (string): Unique identifier of the order. + +#### Request Body + +| Field | Type | Required | Description | +| -------- | ------ | -------- | ------------------------------------ | +| `status` | string | Yes | Set to `IGNORE` to cancel the order. | + +#### Request Example + +```bash +curl --location --request PUT 'https://integrations.clopos.com/open-api/v2/orders/108' \ + --header 'Content-Type: application/json' \ + --header 'x-token: oauth_example_token' \ + --data '{ + "status": "IGNORE" + }' +``` + +```javascript +const orderId = 108; + +const response = await fetch(`https://integrations.clopos.com/open-api/v2/orders/${orderId}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + 'x-token': 'oauth_example_token', + }, + body: JSON.stringify({ status: 'IGNORE' }) +}); + +const data = await response.json(); +``` + +```python +import requests + +order_id = 108 +url = f"https://integrations.clopos.com/open-api/v2/orders/{order_id}" +headers = { + "Content-Type": "application/json", + "x-token": "oauth_example_token", +} + +payload = {"status": "IGNORE"} + +response = requests.put(url, headers=headers, json=payload) +order = response.json() +``` + +#### Response + +##### 200 OK — Order updated + +```json +{ + "success": true, + "data": { + "id": 108, + "venue_id": 1, + "type": "CALL_CENTER_ORDER", + "integration": "call_center_new", + "integration_uuid": null, + "integration_id": null, + "customer_ref_id": null, + "integration_status": "CREATED", + "status": "IGNORE", + "created_at": "2026-02-02T13:45:53.000000Z", + "updated_at": "2026-02-02T17:46:02.000000Z", + "integration_response": null + } +} +``` + +##### 400 Bad Request — Invalid status + +```json +{ + "success": false, + "error": "validation_failed", + "message": "Status is not allowed" +} +``` + +#### Field Reference + +| Field | Type | Description | +| ---------------------- | ----------------- | ------------------------------------------- | +| `id` | integer | Order identifier. | +| `venue_id` | integer | Venue that owns the order. | +| `type` | string | Source of the order. | +| `integration` | string | Integration channel. | +| `integration_uuid` | string (nullable) | UUID from the integration source. | +| `integration_id` | string (nullable) | External ID from the integration source. | +| `customer_ref_id` | string (nullable) | External customer reference ID. | +| `integration_status` | string | State reported by the upstream integration. | +| `status` | string | Updated lifecycle state (e.g., `IGNORE`). | +| `integration_response` | object (nullable) | Response data from the integration, if any. | +| `created_at` | string | Creation timestamp (ISO 8601). | +| `updated_at` | string | Last update timestamp (ISO 8601). | + +#### Notes + +* Request body must include only the status field as shown. +* Currently, only the `IGNORE` status transition is supported through this endpoint. + +## Overview + +### API Overview (v2) + +Source: + +Base URL and authentication changes for Clopos Open API v2 + +!!! note + Version 2 of the Clopos Open API introduces JWT-based authentication and + simplifies request headers. After authentication you only need to send + `x-token` with each call. + +#### Base URL + +```bash +https://integrations.clopos.com/open-api/v2 +``` + +#### What changed in v2 + +* Endpoints live under `/open-api/v2`. +* `/auth` now requires an `integrator_id` along with your existing client credentials. +* `venue_id` is **not** part of the auth payload. +* Subsequent requests require only the `x-token` header; brand and venue headers are no longer needed. +* Auth responses now return both `expires_in` and `expires_at` (epoch seconds). + +#### Authentication flow + + +**1. Collect credentials** + +Use your `client_id`, `client_secret`, `brand`, and `integrator_id`. Clopos issues the `integrator_id`; the other three come from the customer's back office (**Add-ons → Open API**). See [Authentication](https://developer.clopos.com/docs/authentication#where-the-client-id-and-client-secret-come-from). + + +**2. Call /v2/auth** + +Exchange credentials for a JWT access token and note the `expires_at` value. + + +**3. Call other endpoints** + +Include only `x-token` with the JWT you received. + +##### Required header for all v2 endpoints (except `/auth`) + +```bash +x-token: your_jwt_token_here +``` + +##### Sample authenticated request + +```bash +curl -X GET https://integrations.clopos.com/open-api/v2/orders \ + -H "x-token: your_jwt_token_here" +``` + +## Price Lists + +### List Price Lists + +Source: + +`GET /v2/price-lists` + +Retrieve all price lists configured for the brand. + +This endpoint retrieves all price lists. A **price list** is a named set of product prices that can be applied to specific venues or sales channels — for example, a dedicated price list for delivery orders that differs from in-store prices. + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Query Parameters + +- `` (integer): Maximum number of price lists to return per page (1-999). + +- `` (array): Include related data in the response. Supported value: `prices` — embeds the individual product prices that belong to each list. + +- `` (array): Sort the results. Supported fields: `id`, `name`, `created_at`. Use array notation, e.g. `sort[0][0]=name&sort[0][1]=asc`. + +- `` (string): Comma-separated list of fields to include in the response (e.g. `id,name,status`). + +#### Request Example + +```bash +curl "https://integrations.clopos.com/open-api/v2/price-lists?with[]=prices" \ + -H "x-token: YOUR_ACCESS_TOKEN" +``` + +```javascript +const response = await fetch( + "https://integrations.clopos.com/open-api/v2/price-lists?with[]=prices", + { headers: { "x-token": "YOUR_ACCESS_TOKEN" } } +); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/price-lists", + params={"with[]": "prices"}, + headers={"x-token": "YOUR_ACCESS_TOKEN"}, +) +data = response.json() +``` + +#### Response Example + +```json +{ + "data": [ + { + "id": 1, + "name": "Delivery Prices", + "description": "Prices applied to delivery orders", + "status": true, + "prices": [ + { + "id": 10, + "list_id": 1, + "product_id": 105, + "price": 12.5 + } + ], + "created_at": "2026-01-13T14:08:49.000000Z", + "updated_at": "2026-01-13T10:22:12.000000Z" + } + ], + "pagination": { + "page": 1, + "per_page": 50, + "total": 1, + "total_pages": 1 + } +} +``` + +#### Field Reference + +##### Price List Object + +| Field | Type | Description | +| ------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `id` | integer | Unique identifier for the price list. | +| `name` | string | Display name of the price list (e.g., "Delivery Prices"). | +| `description` | string (nullable) | Optional description of the price list, or `null`. | +| `status` | boolean | Whether the price list is active. | +| `prices` | array | Individual product prices in this list. Included only when requested via `with[]=prices`. See [Price object](https://developer.clopos.com/docs/api-reference/v2/price-lists/get-prices). | +| `created_at` | string | Creation timestamp (ISO 8601). | +| `updated_at` | string | Last update timestamp (ISO 8601). | + +### List Prices + +Source: + +`GET /v2/price-lists/prices` + +Retrieve the individual product prices that belong to price lists. + +This endpoint retrieves the individual **prices** stored across all price lists. Each entry maps a product to its price within a specific price list, letting you read product pricing per channel without loading every list separately. + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Query Parameters + +- `` (integer): Maximum number of prices to return per page (1-999). + +- `` (array): Filter prices by specific fields. Use array notation: `filters[0][0]=field_name&filters[0][1]=value`. Supported fields: `id`, `product_id`, `list_id`. + +- `` (array): Include related data in the response. Supported values: `product` (embeds the related product) and `list` (embeds the related price list). + +#### Request Example + +```bash +curl "https://integrations.clopos.com/open-api/v2/price-lists/prices?filters[0][0]=list_id&filters[0][1]=1" \ + -H "x-token: YOUR_ACCESS_TOKEN" +``` + +```javascript +const response = await fetch( + "https://integrations.clopos.com/open-api/v2/price-lists/prices?filters[0][0]=list_id&filters[0][1]=1", + { headers: { "x-token": "YOUR_ACCESS_TOKEN" } } +); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/price-lists/prices", + params={"filters[0][0]": "list_id", "filters[0][1]": "1"}, + headers={"x-token": "YOUR_ACCESS_TOKEN"}, +) +data = response.json() +``` + +#### Response Example + +```json +{ + "data": [ + { + "id": 10, + "list_id": 1, + "product_id": 105, + "price": 12.5 + }, + { + "id": 11, + "list_id": 1, + "product_id": 106, + "price": 8.0 + } + ], + "pagination": { + "page": 1, + "per_page": 50, + "total": 2, + "total_pages": 1 + } +} +``` + +#### Field Reference + +##### Price Object + +| Field | Type | Description | +| ------------ | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | integer | Unique identifier for the price entry. | +| `list_id` | integer | ID of the [price list](https://developer.clopos.com/docs/api-reference/v2/price-lists/get-price-lists) this price belongs to. | +| `product_id` | integer | ID of the product this price applies to. | +| `price` | number | The product's price within this price list. | +| `product` | object (nullable) | The related product. Included only when requested via `with[]=product`. See [Product object](https://developer.clopos.com/docs/api-reference/v2/products/get-all-products). | +| `list` | object (nullable) | The related price list. Included only when requested via `with[]=list`. See [Price List object](https://developer.clopos.com/docs/api-reference/v2/price-lists/get-price-lists). | + +## Products + +### List Products + +Source: + +`GET /v2/products` + +Get the product catalog with advanced filtering and pagination. + +#### Overview + +This endpoint allows you to retrieve your branch-based product catalog. It offers a multitude of filtering options such as `type`, `category_id`, and `tags`, and supports five main product types: `GOODS`, `DISH`, `TIMER`, `PREPARATION`, and `INGREDIENT`. + +The returned data includes product variants (`modifications`), modifiers (`modificator_groups`), recipes (`recipe`), and all other related data. + +##### Product Types and Behaviors + +While all product types are fundamentally "products," each has its own specific models and behaviors: + +* **GOODS:** These can have variants (`modifications`). + * **With Variants:** If a product has variants, only those variants can be sold. The main product acts as a parent and cannot be sold itself. Each modification behaves like a standard `GOODS` product without variants. + * **Without Variants:** Standard products that can be sold directly. + +* **DISH:** This type can have `modificator_groups` (modifiers). + * **Modifiers:** Modifiers (`Modificator`) are used exclusively for `DISH` type products. They represent add-on options like "Spice Level" or "Extra Lavash." + +* **TIMER:** Represents time-based services (e.g., PS5 rental). Pricing is determined by rules defined in the `setting` field. + +* **PREPARATION:** Semi-finished items that have their own recipe and are used in the production of other `DISH` items. + +* **INGREDIENT:** Raw materials used in production. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/products +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Query Parameters + +All parameters are standard URL query parameters. Array and filter values use PHP/Laravel bracket notation — **not** a JSON blob. Arrays are indexed (`with[0]=category&with[1]=station`), and each filter is a tuple under `filters[N]`: field name at `filters[N][0]`, value at `filters[N][1]` (or `filters[N][1][M]` when the value is itself an array). + +- `` (integer): Page number for pagination. + +- `` (integer): Products per page. Maximum: 100. + +- `` (array[string]): + + Related resources to include in each product. Repeat with indexed brackets. Common values: `category`, `station`, `modifications`, `modifications.codes`, `taxes`, `codes`, `modificator_groups`, `recipe`, `packages`, `tags`. + **Example:** `with[0]=category&with[1]=station&with[2]=modifications` + +- `` (string): + + Comma-separated list of fields to include in the response. `id`, `name`, and `type` are always returned. + **Example:** `selects=id,name,type,price,image` + +- `` (array): Zero or more filter tuples, where `N` is a 0-based index. Each tuple is `[field_name, value]`. `value` may be a scalar (`filters[N][1]=...`) or an array (`filters[N][1][0]=...&filters[N][1][1]=...`). See the **Filtering** section for the full list of supported fields. + +#### Filtering + +Each filter occupies its own index under `filters[]`. Stack multiple filters by incrementing the outer index — for example `filters[0]` for `type`, `filters[1]` for `inventory_behavior`, and so on. The outer index order does not matter; only uniqueness does. + +- `type` (array[string]): + + Product type. Possible values: `GOODS`, `DISH`, `TIMER`, `PREPARATION`, `INGREDIENT`. + **Example:** `filters[0][0]=type&filters[0][1][0]=GOODS&filters[0][1][1]=DISH` + +- `category_id` (array[integer]): + + Products belonging to the specified category IDs. + **Example:** `filters[0][0]=category_id&filters[0][1][0]=1&filters[0][1][1]=3` + +- `station_id` (array[integer]): + + Products assigned to the specified station IDs. + **Example:** `filters[0][0]=station_id&filters[0][1][0]=1&filters[0][1][1]=2` + +- `tags` (array[integer]): + + Products with the specified tag IDs. + **Example:** `filters[0][0]=tags&filters[0][1][0]=1&filters[0][1][1]=2` + +- `giftable` (string): + + `"1"` = giftable, `"0"` = not giftable. + **Example:** `filters[0][0]=giftable&filters[0][1]=1` + +- `discountable` (string): + + `"1"` = discountable, `"0"` = not discountable. + **Example:** `filters[0][0]=discountable&filters[0][1]=1` + +- `inventory_behavior` (string): + + Inventory tracking mode. Allowed values: `"0"` (`MINUS_INGREDIENTS` — deduct recipe ingredients on sale, typical for `DISH`), `"1"` (`MINUS_SELF` — deduct the product itself from stock, countable `GOODS`/`INGREDIENT`), `"3"` (`PASSIVE` — no inventory tracking, uncountable). + **Example:** `filters[0][0]=inventory_behavior&filters[0][1]=0` + +- `haveIngredients` (string): + + `"1"` = has a recipe/ingredients. + **Example:** `filters[0][0]=haveIngredients&filters[0][1]=1` + +- `sold_by_portion` (string): + + `"1"` = sold by portion. + **Example:** `filters[0][0]=sold_by_portion&filters[0][1]=1` + +- `has_variants` (string): + + `"1"` = has variants (`modifications`). + **Example:** `filters[0][0]=has_variants&filters[0][1]=1` + +- `has_modifiers` (string): + + `"1"` = has a modifier group (`modificator_groups`). + **Example:** `filters[0][0]=has_modifiers&filters[0][1]=1` + +- `has_barcode` (string): + + `"1"` = has at least one barcode. The filter still works, but the top-level `barcode` string on the product is **deprecated** — request `with[]=codes` and read barcodes from the `codes` array instead. + **Example:** `filters[0][0]=has_barcode&filters[0][1]=1` + +- `has_service_charge` (string): + + `"1"` = service charge applies. + **Example:** `filters[0][0]=has_service_charge&filters[0][1]=1` + +##### Combining filters + +Stack filters by incrementing the outer index. Scalar and array values can be mixed freely: + +``` +?page=1&limit=50 + &filters[0][0]=type&filters[0][1][0]=GOODS&filters[0][1][1]=DISH&filters[0][1][2]=TIMER + &filters[1][0]=inventory_behavior&filters[1][1]=0 +``` + +(Line breaks shown only for readability — the real URL must be a single string with no whitespace. Brackets should be URL-encoded by your HTTP client; `curl` users can pass `--globoff` to avoid shell interpretation.) + +#### Request Examples + +```bash +# Basic request with pagination and selects +curl --globoff 'https://integrations.clopos.com/open-api/v2/products?page=1&limit=100&selects=id,name,type' \ + -H "x-token: oauth_example_token" +``` + +```bash +# Relations + two filters (type IN (GOODS,DISH,TIMER) AND inventory_behavior = 0) +curl --globoff 'https://integrations.clopos.com/open-api/v2/products?with[0]=category&with[1]=station&with[2]=modifications&with[3]=modifications.codes&with[4]=taxes&with[5]=codes&page=1&limit=50&filters[0][0]=type&filters[0][1][0]=GOODS&filters[0][1][1]=DISH&filters[0][1][2]=TIMER&filters[1][0]=inventory_behavior&filters[1][1]=0' \ + -H "x-token: oauth_example_token" +``` + +```javascript +// URLSearchParams handles the bracket encoding for you +const params = new URLSearchParams({ + page: '1', + limit: '50', + 'with[0]': 'category', + 'with[1]': 'station', + 'with[2]': 'modifications', + 'with[3]': 'modifications.codes', + 'with[4]': 'taxes', + 'with[5]': 'codes', + 'filters[0][0]': 'type', + 'filters[0][1][0]': 'GOODS', + 'filters[0][1][1]': 'DISH', + 'filters[0][1][2]': 'TIMER', + 'filters[1][0]': 'inventory_behavior', + 'filters[1][1]': '0', +}); + +const response = await fetch(`https://integrations.clopos.com/open-api/v2/products?${params}`, { + headers: { 'x-token': 'oauth_example_token' }, +}); + +const result = await response.json(); +console.log(result); +``` + +```python +import requests + +url = "https://integrations.clopos.com/open-api/v2/products" +headers = {"x-token": "oauth_example_token"} +params = { + "page": 1, + "limit": 50, + "with[0]": "category", + "with[1]": "station", + "with[2]": "modifications", + "with[3]": "modifications.codes", + "with[4]": "taxes", + "with[5]": "codes", + "filters[0][0]": "type", + "filters[0][1][0]": "GOODS", + "filters[0][1][1]": "DISH", + "filters[0][1][2]": "TIMER", + "filters[1][0]": "inventory_behavior", + "filters[1][1]": 0, +} + +response = requests.get(url, headers=headers, params=params) +result = response.json() +``` + +#### Response + +```json +{ + "success": true, + "data": [ + { + "id": 1, + "parent_id": null, + "station_id": null, + "category_id": null, + "unit_id": 1, + "type": "INGREDIENT", + "name": "Test_Tomato", + "parent_name": "", + "full_name": "Test_Tomato", + "position": null, + "barcode": null, + "gov_code": null, + "status": 1, + "hidden": 0, + "sold_by_weight": false, + "discountable": true, + "giftable": false, + "has_modifications": false, + "description": null, + "price": 0, + "cost_price": 0, + "cooking_time": 0, + "inventory_behavior": 0, + "low_stock": 0, + "unit_weight": 0, + "venues": [], + "media": [], + "created_at": "2026-01-13 20:04:05", + "updated_at": "2026-01-13 20:04:05" + }, + { + "id": 2, + "parent_id": null, + "station_id": null, + "category_id": null, + "unit_id": 1, + "type": "INGREDIENT", + "name": "Test_Onion", + "parent_name": "", + "full_name": "Test_Onion", + "position": null, + "barcode": null, + "gov_code": null, + "status": 1, + "hidden": 0, + "sold_by_weight": false, + "discountable": true, + "giftable": false, + "has_modifications": false, + "description": null, + "price": 0, + "cost_price": 1, + "cooking_time": 0, + "inventory_behavior": 0, + "low_stock": 0, + "unit_weight": 0, + "venues": [], + "media": [], + "created_at": "2026-01-13 20:04:06", + "updated_at": "2026-04-01 17:05:36" + } + ], + "total": 284 +} +``` + +#### Field Reference + +##### Product Object + +| Field | Type | Description | +| -------------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | integer | Unique product identifier. | +| `parent_id` | integer (nullable) | ID of the parent product for a variant. A row with `type: "MODIFICATION"` is a **variant** of the `GOODS` product referenced here — "modification" and "variant" mean the same thing in this API, and a variant carries the full product schema (same fields as the parent, with its own `price`, `cost_price`, stock, barcodes, etc.). | +| `station_id` | integer (nullable) | ID of the preparation station assigned to this product. | +| `category_id` | integer (nullable) | ID of the category this product belongs to. | +| `unit_id` | integer | ID of the unit of measurement. | +| `type` | string | Product type: `GOODS`, `DISH`, `TIMER`, `PREPARATION`, `INGREDIENT`, `MODIFICATION`, `MODIFIER`. | +| `name` | string | Product name. | +| `parent_name` | string | Name of the parent product (empty string if none). | +| `full_name` | string | Full product name including variant info (e.g., "Fanta 0.5 L"). | +| `position` | integer (nullable) | Display order position within the category. | +| `barcode` | string (nullable) | **Deprecated.** Legacy single-barcode field, kept for backwards compatibility and not guaranteed to be populated. For current barcodes, request `with[]=codes` and read from the `codes` array. | +| `gov_code` | string (nullable) | Government/tax code for the product. | +| `status` | integer | `1` = active, `0` = inactive. | +| `hidden` | integer | `1` = hidden from menus, `0` = visible. | +| `sold_by_weight` | boolean | Whether the product is sold by weight rather than quantity. | +| `discountable` | boolean | Whether discounts can be applied to this product. | +| `giftable` | boolean | Whether this product can be given as a gift/complimentary item. | +| `has_modifications` | boolean | If `true`, the product has variants in the `modifications` array. | +| `description` | string (nullable) | Product description text. | +| `price` | number | Base selling price. For parent GOODS with variants, this may be `0` since variants carry their own prices. | +| `cost_price` | number | Cost price used for margin calculations. | +| `cooking_time` | integer | Estimated preparation time in minutes. | +| `inventory_behavior` | integer | Inventory tracking mode. `0` = `MINUS_INGREDIENTS` — on sale, deduct the recipe's ingredients from stock (typical for `DISH`). `1` = `MINUS_SELF` — deduct the product itself from stock (countable `GOODS` / `INGREDIENT`). `3` = `PASSIVE` — no inventory tracking (uncountable). | +| `low_stock` | integer | Low stock threshold for alerts. | +| `unit_weight` | number | Physical weight of a single unit, in **kilograms**. For example, if `unit_id` resolves to `pcs`, this is how much one piece weighs (a single packet that weighs 3 kg is stored as `3`). Independent of `sold_by_weight`; used for logistics, shipping, and stock-by-weight calculations, not for pricing mode. | +| `venues` | array | Venue-specific availability and pricing overrides. | +| `media` | array | Image attachments. See [Media object](https://developer.clopos.com/docs/common-objects#media). | +| `created_at` | string | Creation timestamp. | +| `updated_at` | string | Last update timestamp. | + +##### Variant Object (`modifications`) + +Represents different versions (e.g., size, color) of a `GOODS` type product. + +A variant has the **same shape as a product** — every field listed in the [Product Object](#field-reference) above (`id`, `parent_id`, `category_id`, `unit_id`, `price`, `cost_price`, `unit_weight`, `inventory_behavior`, `media`, `venues`, `created_at`, `updated_at`, …) is present on each variant. The only differences worth calling out: + +* `type` is always `MODIFICATION`. +* `parent_id` points at the parent `GOODS` product instead of being `null`. +* `full_name` combines the parent name with the variant name (e.g. `"Fanta 0.5 L"`). +* The variant carries its own `price`, `cost_price`, `barcode`/`codes`, `status`, stock, etc. — the parent's values are not inherited at sale time. + +##### Modifier Group (`modificator_groups`) + +Defines groups of options that can be added to a `DISH` type product (e.g., "Pizza Toppings"). + +| Field | Type | Description | +| -------------- | ------- | ------------------------------------------------------- | +| `id` | integer | The group's identifier. | +| `name` | string | The name of the group (e.g., "Spice Level"). | +| `type` | integer | Selection rule (`1`: Single-choice, `0`: Multi-choice). | +| `min_select` | integer | Minimum number of selections. | +| `max_select` | integer | Maximum number of selections. | +| `modificators` | array | List of selectable items. See **Modifier Object**. | + +##### Modifier Object (`modificators`) + +| Field | Type | Description | +| ------------ | ----------------- | ---------------------------------------------------------------------------- | +| `id` | integer | The modifier's identifier. | +| `name` | string | The name of the modifier (e.g., "Medium Hot"). | +| `price` | number | The additional price for the option. | +| `ingredient` | object (nullable) | If the modifier is linked to an ingredient, contains ingredient information. | + +##### Timer Settings (`setting`) + +Contains the time-based pricing rules for `TIMER` type products. + +| Field | Type | Description | +| ---------- | ------- | ------------------------------------------------------------------ | +| `interval` | integer | The pricing interval in minutes. | +| `prices` | array | Prices for different time periods. `[{ "price": 3, "from": 120 }]` | + +##### Recipe Item (`recipe`) + +| Field | Type | Description | +| --------------- | ------- | --------------------------------------- | +| `ingredient_id` | integer | The product ID of the recipe component. | +| `name` | string | The name of the component. | +| `gross` | string | Gross amount. | +| `net` | string | Net amount. | + +##### Package Object (`packages`) + +Specifies the purchasing packages defined for `INGREDIENT` type products. + +| Field | Type | Description | +| ------- | ------- | -------------------------------------------------- | +| `id` | integer | The package's identifier. | +| `name` | string | The name of the package (e.g., "Bundle 10 pcs"). | +| `equal` | integer | The number of base units contained in the package. | + +### Get Product by ID + +Source: + +`GET /v2/products/{id}` + +Retrieve a single product with type-specific details. + +#### Purpose + +Returns a single product from the Clopos catalog, along with related data specific to its type (variants, modifiers, recipe, timer settings, etc.). Use the `with` parameters to fetch only the sub-resources you need. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/products/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Path Parameters + +- `` (string): The product ID (integer or UUID). + +#### Query Parameters + +- `` (string): Related data selector. Example: `taxes`, `unit`, `modifications`, `modificator_groups`, `recipe`, `packages`, `media`, `tags`, `setting`. You can include multiple `with` parameters. + +> Supported `with` values may vary based on your backend version. + +#### Request Example + +```bash +curl -X GET "https://integrations.clopos.com/open-api/v2/products/419?with[]=modifications&with[]=taxes" \ + -H "x-token: oauth_example_token" \ +``` + +```bash +curl -X GET "https://integrations.clopos.com/open-api/v2/products/1?with[]=modificator_groups&with[]=recipe" \ + -H "x-token: oauth_example_token" \ +``` + +```javascript +const params = new URLSearchParams([ + ['with[]', 'taxes'], + ['with[]', 'unit'], + ['with[]', 'modificator_groups.modificators.ingredient.unit'], + ['with[]', 'recipe'], + ['with[]', 'packages'] +]); + +const response = await fetch(`https://integrations.clopos.com/open-api/v2/products/1?${params}`, { + headers: { + 'x-token': 'oauth_example_token', + } +}); + +const product = await response.json(); +``` + +#### Response + +##### 200 OK — Product found + +```json +{ + "success": true, + "data": { + "id": 1, + "parent_id": null, + "station_id": null, + "category_id": null, + "unit_id": 1, + "type": "INGREDIENT", + "name": "Test_Tomato", + "parent_name": "", + "full_name": "Test_Tomato", + "position": null, + "barcode": null, + "gov_code": null, + "status": 1, + "hidden": 0, + "sold_by_weight": false, + "discountable": true, + "giftable": false, + "has_modifications": false, + "description": null, + "price": 0, + "cost_price": 0, + "cooking_time": 0, + "inventory_behavior": 0, + "low_stock": 0, + "unit_weight": 0, + "venues": [], + "media": [], + "created_at": "2026-01-13 20:04:05", + "updated_at": "2026-01-13 20:04:05" + } +} +``` + +##### 404 Not Found — Product does not exist + +```json +{ + "success": false, + "error": "resource_not_found", + "message": "Product not found" +} +``` + +#### Field Reference + +[See the full breakdown of the `Product` object and nested structures such as `modifications` and `modificator_groups` on the List Products page.](https://developer.clopos.com/docs/api-reference/v2/products/get-all-products#field-reference) + +##### Product Object + +| Field | Type | Description | +| -------------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | integer | Unique product identifier. | +| `parent_id` | integer (nullable) | ID of the parent product for a variant. A row with `type: "MODIFICATION"` is a **variant** of the `GOODS` product referenced here — "modification" and "variant" mean the same thing in this API, and a variant carries the full product schema (same fields as the parent, with its own `price`, `cost_price`, stock, barcodes, etc.). | +| `station_id` | integer (nullable) | ID of the preparation station assigned to this product. | +| `category_id` | integer (nullable) | ID of the category this product belongs to. | +| `unit_id` | integer | ID of the unit of measurement. | +| `type` | string | Product type: `GOODS`, `DISH`, `TIMER`, `PREPARATION`, `INGREDIENT`, `MODIFICATION`, `MODIFIER`. | +| `name` | string | Product name. | +| `parent_name` | string | Name of the parent product (empty string if none). | +| `full_name` | string | Full product name including variant info (e.g., "Fanta 0.5 L"). | +| `position` | integer (nullable) | Display order position within the category. | +| `barcode` | string (nullable) | **Deprecated.** Legacy single-barcode field, kept for backwards compatibility and not guaranteed to be populated. For current barcodes, request `with[]=codes` and read from the `codes` array. | +| `gov_code` | string (nullable) | Government/tax code for the product. | +| `status` | integer | `1` = active, `0` = inactive. | +| `hidden` | integer | `1` = hidden from menus, `0` = visible. | +| `sold_by_weight` | boolean | Whether the product is sold by weight rather than quantity. | +| `discountable` | boolean | Whether discounts can be applied to this product. | +| `giftable` | boolean | Whether this product can be given as a gift/complimentary item. | +| `has_modifications` | boolean | If `true`, the product has variants in the `modifications` array. | +| `description` | string (nullable) | Product description text. | +| `price` | number | Base selling price. For parent GOODS with variants, this may be `0` since variants carry their own prices. | +| `cost_price` | number | Cost price used for margin calculations. | +| `cooking_time` | integer | Estimated preparation time in minutes. | +| `inventory_behavior` | integer | Inventory tracking mode. `0` = `MINUS_INGREDIENTS` — on sale, deduct the recipe's ingredients from stock (typical for `DISH`). `1` = `MINUS_SELF` — deduct the product itself from stock (countable `GOODS` / `INGREDIENT`). `3` = `PASSIVE` — no inventory tracking (uncountable). | +| `low_stock` | integer | Low stock threshold for alerts. | +| `unit_weight` | number | Physical weight of a single unit, in **kilograms**. For example, if `unit_id` resolves to `pcs`, this is how much one piece weighs (a single packet that weighs 3 kg is stored as `3`). Independent of `sold_by_weight`; used for logistics, shipping, and stock-by-weight calculations, not for pricing mode. | +| `venues` | array | Venue-specific availability and pricing overrides. | +| `media` | array | Image attachments. See [Media object](https://developer.clopos.com/docs/common-objects#media). | +| `created_at` | string | Creation timestamp. | +| `updated_at` | string | Last update timestamp. | + +#### Notes + +* If the `id` parameter is in the wrong format, the backend returns a `400` error; validate it on the client side. +* Since `with` parameters are evaluated sequentially, avoid using the same key more than once. +* Type-specific heavy relationships (for example, large `recipe` or `modificator_groups`) can produce large responses; request only what you need. +* Some fields may be empty or null depending on the product type; use the `type` field to drive conditional rendering on the client. +* For TIMER products, the `setting.prices` array represents additional fees applied after a certain duration. +* For INGREDIENT products, the `packages` field shows the package sizes used in stock entries; if not applicable, it is an empty array. + +### Get Stop List + +Source: + +`GET /v2/products/stop-list` + +Get stop list data for specific products + +#### Purpose + +Retrieve stop list data for specific products. The stop list indicates product limitations such as stock limits. If a product is not returned in the response, it means that product does not have any stop list limitations. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/products/stop-list +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Query Parameters + +##### Filters + +You can filter by product IDs to get stop list data for specific products. + +| Parameter | Type | Required | Description | +| --------------- | ------ | -------- | ------------------------------------------------------ | +| `filters[0][0]` | string | No | Filter field name. Use `"id"` to filter by product ID. | +| `filters[0][1]` | array | No | Array of product IDs to filter. | + +##### Filter Syntax + +To filter by product IDs, use the following format: + +``` +filters[0][0]=id&filters[0][1][0]=1&filters[0][1][1]=332 +``` + +This will filter for products with IDs `1` and `332`. + +#### Request Example + +```bash +curl --location --globoff 'https://integrations.clopos.com/open-api/v2/products/stop-list?filters[0][0]=id&filters[0][1][0]=1&filters[0][1][1]=332' \ + --header 'x-token: oauth_example_token' \ +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/products/stop-list?filters[0][0]=id&filters[0][1][0]=1&filters[0][1][1]=332', { + headers: { + 'x-token': 'oauth_example_token', + } +}); + +const data = await response.json(); +``` + +```python +import requests + +url = "https://integrations.clopos.com/open-api/v2/products/stop-list" +headers = { + "x-token": "oauth_example_token", +} +params = { + "filters[0][0]": "id", + "filters[0][1][0]": 1, + "filters[0][1][1]": 332 +} + +response = requests.get(url, headers=headers, params=params) +data = response.json() +``` + +#### Response + +##### 200 OK — Success + +Returns an array of stop list entries for the requested products. If a product does not have stop list limitations, it will not appear in the response. + +```json +{ + "success": true, + "data": [ + { + "id": 54, + "limit": 0, + "timestamp": 1761202010781 + }, + { + "id": 57, + "limit": 3, + "timestamp": 1761202001368 + }, + { + "id": 275, + "limit": 5, + "timestamp": 1762929390368 + } + ] +} +``` + +!!! note + When no products are on the stop list, the response returns an empty `data` array: `{"success": true, "data": []}`. This is normal and indicates no products currently have stock limitations. + +##### 400 Bad Request — Invalid Parameters + +```json +{ + "success": false, + "error": "invalid_parameter", + "message": "Invalid filter parameters" +} +``` + +##### 401 Unauthorized — Missing Header + +```json +{ + "success": false, + "error": "unauthorized", + "message": "Missing authentication headers" +} +``` + +#### Field Reference + +##### Stop List Entry Object + +| Field | Type | Description | +| ----------- | ------- | ------------------------------------------------------------------------------------------------ | +| `id` | integer | Product ID. This corresponds to the product identifier. | +| `limit` | integer | Stock limit for the product. `0` means the product is out of stock or has no available quantity. | +| `timestamp` | integer | Unix timestamp (in milliseconds) when the stop list entry was last updated. | + +#### Notes + +* The `id` field in the response represents the `product_id`. +* If a product is not included in the response data, it means that product does not have any stop list limitations. +* Use the `filters` parameter to query specific products by their IDs. +* The `limit` field indicates the available stock limit. A value of `0` typically means the product is unavailable. +* The `timestamp` field shows when the stop list entry was last updated, useful for tracking changes. + +## Receipts + +### Close Receipt + +Source: + +`POST /v2/receipts/{id}/close` + +Close an existing receipt with payment methods and closing timestamp + +#### Purpose + +Close an existing receipt by updating its payment methods and setting the closing timestamp. This endpoint is used to finalize a receipt that was previously created but not yet closed. + +#### HTTP Request + +```http +POST https://integrations.clopos.com/open-api/v2/receipts/{id}/close +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Path Parameters + +| Parameter | Type | Description | +| --------- | ------ | ------------------------------------------ | +| `id` | number | Unique identifier of the receipt to close. | + +#### Request Body + +| Field | Type | Required | Description | +| ----------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------ | +| `payment_methods` | array | Yes | List of payment methods with amounts. See [Payment method](https://developer.clopos.com/docs/common-objects#payment-method-in-receipts). | +| `closed_at` | string | No | Closing timestamp (YYYY-MM-DD HH:mm:ss). Defaults to current time if omitted. | + +##### `payment_methods[]` + +| Field | Type | Required | Description | +| -------- | ------ | -------- | ------------------------------------------- | +| `id` | number | Yes | Payment method ID. | +| `name` | string | Yes | Payment method name (e.g., "Cash", "Card"). | +| `amount` | number | Yes | Amount paid using this method. | + +#### Request Example + +```bash +curl --location --request POST 'https://integrations.clopos.com/open-api/v2/receipts/10950/close' \ + --header 'Content-Type: application/json' \ + --header 'x-token: oauth_example_token' \ + --data '{ + "payment_methods": [ + { + "id": 2, + "name": "Cash", + "amount": 8140 + } + ], + "closed_at": "2026-01-20 09:59:54" + }' +``` + +```javascript +const receiptId = 10950; + +const response = await fetch(`https://integrations.clopos.com/open-api/v2/receipts/${receiptId}/close`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'x-token': 'oauth_example_token', + }, + body: JSON.stringify({ + payment_methods: [ + { + id: 2, + name: 'Cash', + amount: 8140 + } + ], + closed_at: '2026-01-20 09:59:54' + }) +}); + +const receipt = await response.json(); +``` + +```python +import requests + +receipt_id = 10950 +url = f"https://integrations.clopos.com/open-api/v2/receipts/{receipt_id}/close" +headers = { + "Content-Type": "application/json", + "x-token": "oauth_example_token", +} +payload = { + "payment_methods": [ + { + "id": 2, + "name": "Cash", + "amount": 8140 + } + ], + "closed_at": "2026-01-20 09:59:54" +} + +response = requests.post(url, headers=headers, json=payload) +receipt = response.json() +``` + +#### Response + +##### 200 OK — Receipt Closed + +```json +{ + "success": true, + "message": "Receipt closed", + "data": { + "id": 10950, + "closed_at": "2026-01-20 09:59:54", + "payment_methods": [ + { + "id": 2, + "name": "Cash", + "amount": 8140 + } + ] + } +} +``` + +##### 400 Bad Request — Validation Error + +```json +{ + "success": false, + "error": "validation_failed", + "message": "closed_at must be greater than created_at" +} +``` + +##### 404 Not Found — Receipt Not Found + +```json +{ + "success": false, + "error": "not_found", + "message": "Receipt not found" +} +``` + +#### Field Reference + +##### Response fields + +| Field | Type | Description | +| ---------------------- | ------- | --------------------------------------------------------------- | +| `success` | boolean | Indicates the result of the request. | +| `message` | string | Human-readable status message. | +| `data.id` | number | Receipt identifier that was closed. | +| `data.closed_at` | string | Closing timestamp applied to the receipt (YYYY-MM-DD HH:mm:ss). | +| `data.payment_methods` | array | Payment methods recorded on the receipt. | + +##### `payment_methods[]` + +| Field | Type | Description | +| -------- | ------ | ------------------------------------------- | +| `id` | number | Payment method ID. | +| `name` | string | Payment method name (e.g., "Cash", "Card"). | +| `amount` | number | Amount paid using this method. | + +#### Notes + +* The receipt must be in an open state (`status: 1`) to be closed through this endpoint. +* If `closed_at` is omitted, the server uses the current timestamp. +* The `closed_at` value must be later than the receipt's `created_at` timestamp. +* After closing, the receipt's `status` changes to `2` (closed). + +### Get Receipt by CID + +Source: + +`GET /v2/receipts/cid/{cid}` + +Retrieve a receipt by its cid UUID. + +Terminals key receipts by a `cid` UUID, so integrations often hold that rather than the numeric id. Returns exactly the same payload as fetching by id. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/receipts/cid/{cid} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Access + +| Requirement | Value | +| ---------------- | --------------- | +| Integrator scope | `receipts:read` | +| User ability | `RECEIPT_VIEW` | + +The integration user must hold the ability as well as the scope — the scope alone is not enough. + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/receipts/cid/96ab5d26-d6bb-4976-a6f8-9e8806ef6aa5" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/receipts/cid/96ab5d26-d6bb-4976-a6f8-9e8806ef6aa5', { + headers: { 'x-token': 'oauth_example_token' } +}); +const data = await response.json(); +``` + +```python +import requests + +response = requests.get( + "https://integrations.clopos.com/open-api/v2/receipts/cid/96ab5d26-d6bb-4976-a6f8-9e8806ef6aa5", + headers={"x-token": "oauth_example_token"}, +) +data = response.json() +``` + +#### Notes + +* The `cid` must be a well-formed UUID; anything else returns `400` without reaching the API. + +### Get Receipt by ID + +Source: + +`GET /v2/receipts/{id}` + +Retrieve the full details of a specific receipt + +#### Purpose + +Fetch the final state of a single receipt, including payment breakdowns and line items. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/receipts/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Path Parameters + +| Parameter | Type | Description | +| --------- | ------ | ----------------------------------------------------- | +| `id` | number | Unique identifier of the receipt you want to inspect. | + +#### Query Parameters + +- `` (string): + + Include related resources in the response. Supported values: + + * `receipt_products` — line items on the receipt + * `receipt_products.modificators` — modifiers applied to each line item + +#### Request Example + +```bash +# Basic request +curl --location "https://integrations.clopos.com/open-api/v2/receipts/1" \ + -H "x-token: oauth_example_token" + +# With products and modifiers (note: --globoff to avoid shell globbing) +curl --location --globoff "https://integrations.clopos.com/open-api/v2/receipts/1?with[0]=receipt_products.product.unit&with[1]=receipt_products.product.station&with[2]=receipt_products.modificators.modificator_group" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const receiptId = 1; +const headers = { 'x-token': 'oauth_example_token' }; + +// Basic request +const response = await fetch( + `https://integrations.clopos.com/open-api/v2/receipts/${receiptId}`, + { headers } +); +const receipt = await response.json(); + +// With products and modifiers +const params = new URLSearchParams({ + 'with[0]': 'receipt_products.product.unit', + 'with[1]': 'receipt_products.product.station', + 'with[2]': 'receipt_products.modificators.modificator_group' +}); + +const responseWithProducts = await fetch( + `https://integrations.clopos.com/open-api/v2/receipts/${receiptId}?${params}`, + { headers } +); +const receiptWithProducts = await responseWithProducts.json(); +``` + +```python +import requests + +receipt_id = 1 +url = f"https://integrations.clopos.com/open-api/v2/receipts/{receipt_id}" +headers = { + "x-token": "oauth_example_token", +} + +# Basic request +response = requests.get(url, headers=headers) +receipt = response.json() + +# With products and modifiers +params = { + "with[0]": "receipt_products.product.unit", + "with[1]": "receipt_products.product.station", + "with[2]": "receipt_products.modificators.modificator_group" +} + +response = requests.get(url, headers=headers, params=params) +receipt_with_products = response.json() +``` + +#### Response + +##### 200 OK — Receipt + +```json +{ + "success": true, + "data": { + "id": 1, + "venue_id": 1, + "cid": "96ab5d26-d6bb-4976-a6f8-9e8806ef6aa5", + "customer_id": null, + "sale_type_id": 2, + "source": "web", + "guests": 1, + "status": 2, + "order_status": "IN_PROGRESS", + "order_number": "006", + "lock": false, + "total": 30000, + "subtotal": 30000, + "discount_type": 0, + "discount_value": 0, + "discount_rate": 0, + "total_discount": 0, + "service_charge": 0, + "service_charge_value": 0, + "delivery_fee": 0, + "remaining": 0, + "i_tax": 0, + "e_tax": 0, + "total_tax": 0, + "payment_methods": [ + { + "id": 1, + "name": "Cash", + "amount": 30000 + } + ], + "fiscal_id": null, + "loyalty_type": null, + "loyalty_value": null, + "address": null, + "description": null, + "created_at": "2026-01-19 14:51:33", + "updated_at": "2026-01-19 15:07:49", + "closed_at": "2026-01-19 15:07:49", + "shift_date": "2026-01-19", + "receipt_products": [ + { + "id": 1, + "cid": "0fd784b1-ee5a-4745-a130-a849b4e5db2f", + "product_id": 51, + "count": 1, + "portion_size": 1, + "total": 10, + "price": 10, + "subtotal": 10, + "is_gift": false, + "discount_type": 0, + "discount_value": 0, + "discount_rate": 0, + "total_discount": 0, + "receipt_discount": 0, + "loyalty_type": null, + "loyalty_value": null, + "meta": { + "product": { + "name": "Test_Margherita Pizza", + "type": "DISH", + "price": 10, + "barcode": null + } + }, + "modificators": [], + "created_at": "2026-01-19 14:51:34", + "updated_at": "2026-01-19 15:07:53" + } + ] + } +} +``` + +##### 404 Not Found — Invalid ID + +```json +{ + "success": false, + "error": "not_found", + "message": "Receipt not found" +} +``` + +#### Field Reference + +##### Receipt object + +| Field | Type | Description | +| ---------------------- | ------------ | ----------------------------------------------------------------------------------------------------------------- | +| `id` | number | Unique receipt identifier. | +| `cid` | string | Client-generated UUID for the receipt. | +| `venue_id` | number | Venue (location) the receipt belongs to. | +| `customer_id` | number\|null | Customer associated with the receipt. | +| `sale_type_id` | number | Sale type identifier (e.g., dine-in, delivery). | +| `source` | string | Origin of the receipt (e.g., `"web"`, `"pos"`). | +| `guests` | number | Number of guests on the receipt. | +| `status` | number | Receipt status: `1` = open, `2` = closed. | +| `order_status` | string | Order workflow status. One of: `NEW`, `SCHEDULED`, `IN_PROGRESS`, `READY`, `PICKED_UP`, `COMPLETED`, `CANCELLED`. | +| `order_number` | string\|null | External or display order number. | +| `lock` | boolean | Whether the receipt is locked from further changes. | +| `total` | number | Total amount collected. | +| `subtotal` | number | Subtotal before discounts, taxes, and fees. | +| `discount_type` | number | Discount type applied (0 = none). | +| `discount_value` | number | Discount amount or percentage value. | +| `discount_rate` | number | Effective discount rate. | +| `total_discount` | number | Total discount applied to the receipt. | +| `service_charge` | number | Service charge percentage. | +| `service_charge_value` | number | Calculated service charge amount. | +| `delivery_fee` | number | Delivery fee amount. | +| `remaining` | number | Outstanding balance (0 when fully paid). | +| `i_tax` | number | Inclusive tax amount. | +| `e_tax` | number | Exclusive tax amount. | +| `total_tax` | number | Total tax amount (inclusive + exclusive). | +| `payment_methods` | array | Payment breakdown. See [Payment method](https://developer.clopos.com/docs/common-objects#payment-method-in-receipts). | +| `fiscal_id` | string\|null | Fiscal receipt identifier for tax reporting. | +| `loyalty_type` | string\|null | Loyalty program type applied. | +| `loyalty_value` | number\|null | Loyalty discount or points value. | +| `address` | string\|null | Delivery address. | +| `description` | string\|null | Delivery or order notes. | +| `created_at` | string | Receipt creation time (YYYY-MM-DD HH:mm:ss). | +| `updated_at` | string | Last update time (YYYY-MM-DD HH:mm:ss). | +| `closed_at` | string\|null | Receipt close time (YYYY-MM-DD HH:mm:ss). | +| `shift_date` | string | Business day the receipt belongs to (YYYY-MM-DD). | + +See [Payment method](https://developer.clopos.com/docs/common-objects#payment-method-in-receipts) for the `payment_methods[]` structure. + +##### `receipt_products[]` + +Included when `with[]=receipt_products` is passed. Each item represents one line on the receipt. + +| Field | Type | Description | +| ---------------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------- | +| `id` | integer | Line item identifier. | +| `cid` | string | Client-generated UUID for the line item. | +| `product_id` | integer | Product ID from your catalog. | +| `count` | integer | Quantity ordered. | +| `portion_size` | integer | Portion size multiplier (usually `1`). | +| `total` | number | Line total after adjustments. | +| `price` | number | Unit price at the time of sale. | +| `subtotal` | number | Subtotal before receipt-level discounts. | +| `is_gift` | boolean | Whether this item was given as a complimentary gift. | +| `discount_type` | integer | Discount type on this line item (`0` = none). | +| `discount_value` | number | Discount amount or percentage. | +| `discount_rate` | number | Effective discount rate. | +| `total_discount` | number | Total discount on this line item. | +| `receipt_discount` | number | Portion of the receipt-level discount allocated to this item. | +| `loyalty_type` | string (nullable) | Loyalty program type applied to this item. | +| `loyalty_value` | number (nullable) | Loyalty points or discount value. | +| `meta.product.name` | string | Product name at the time of sale. | +| `meta.product.type` | string | Product type (`DISH`, `GOODS`, etc.). | +| `meta.product.price` | number | Product's catalog price at the time of sale. | +| `meta.product.barcode` | string (nullable) | Product barcode. | +| `modificators` | array | Modifiers applied to this item. Included when `with[]=receipt_products.modificators` is passed. Empty array if none. | +| `created_at` | string | When the line item was added (`YYYY-MM-DD HH:mm:ss`). | +| `updated_at` | string | Last update time (`YYYY-MM-DD HH:mm:ss`). | + +#### Notes + +* Closed receipts store the final totals; quantities and amounts cannot be edited through this endpoint. +* Use `receipt_products` for reconciliation with inventory or accounting systems. +* The response also includes `time`, `timestamp`, and `unix` fields for diagnostics; these are omitted from the example for brevity. +* Combine with the list endpoint when you need to cross-check totals before exporting reports. + +### Get Receipt Stock Operations + +Source: + +`GET /v2/receipts/{id}/stock-operations` + +Retrieve the stock deductions ("Çıxarılan ehtiyat") generated by a receipt + +#### Purpose + +Fetch the stock write-offs caused by a single receipt — the inventory deducted from your storages when the receipt's products were sold. Use it to reconcile a sale against the warehouse movements it produced ("Çıxarılan ehtiyat" / stock deduction by receipt id). + +Only the deductions of the receipt itself are returned: each item has `operation_id = null` and a non-null `receipt_product_id`. Manual stock corrections or operations from other documents are excluded. + +This endpoint requires the `receipts:read` scope. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/receipts/{id}/stock-operations +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Path Parameters + +| Parameter | Type | Description | +| --------- | ------ | ---------------------------------------------------------------------------- | +| `id` | number | Unique identifier of the receipt whose stock deductions you want to inspect. | + +#### Request Example + +```bash +curl --location "https://integrations.clopos.com/open-api/v2/receipts/1/stock-operations" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const receiptId = 1; +const headers = { 'x-token': 'oauth_example_token' }; + +const response = await fetch( + `https://integrations.clopos.com/open-api/v2/receipts/${receiptId}/stock-operations`, + { headers } +); +const stockOperations = await response.json(); +``` + +```python +import requests + +receipt_id = 1 +url = f"https://integrations.clopos.com/open-api/v2/receipts/{receipt_id}/stock-operations" +headers = { + "x-token": "oauth_example_token", +} + +response = requests.get(url, headers=headers) +stock_operations = response.json() +``` + +#### Response + +##### 200 OK — Stock operations + +```json +{ + "data": [ + { + "id": 1001, + "receipt_id": 1, + "receipt_product_id": 14, + "product_id": 31042, + "stock_id": 5001, + "storage_id": 3, + "quantity": 1, + "before_quantity": 120, + "after_quantity": 119, + "cost": 8000, + "before_cost": 8000, + "total_cost": 8000, + "operated_at": "2026-01-19 15:07:49", + "product": { + "id": 31042, + "name": "Апельсинли реване" + }, + "stock": { + "id": 5001, + "storage": { + "id": 3, + "name": "Main Storage" + } + } + }, + { + "id": 1002, + "receipt_id": 1, + "receipt_product_id": 15, + "product_id": 31046, + "stock_id": 5002, + "storage_id": 3, + "quantity": 2, + "before_quantity": 50, + "after_quantity": 48, + "cost": 1500, + "before_cost": 1500, + "total_cost": 3000, + "operated_at": "2026-01-19 15:07:49", + "product": { + "id": 31046, + "name": "Ачма узум жевиз" + }, + "stock": { + "id": 5002, + "storage": { + "id": 3, + "name": "Main Storage" + } + } + } + ] +} +``` + +##### 404 Not Found — Invalid ID + +```json +{ + "success": false, + "error": "not_found", + "message": "Receipt not found" +} +``` + +#### Field Reference + +##### Stock operation object + +| Field | Type | Description | +| -------------------- | ------ | ------------------------------------------------------------------------------------- | +| `id` | number | Stock operation identifier. | +| `receipt_id` | number | Receipt the operation belongs to. | +| `receipt_product_id` | number | Receipt product line that produced the write-off (always set for receipt deductions). | +| `product_id` | number | Product whose stock was deducted. | +| `stock_id` | number | Stock record affected by the operation. | +| `storage_id` | number | Storage the stock belongs to. | +| `quantity` | number | Quantity deducted from stock. | +| `before_quantity` | number | Stock quantity before the operation. | +| `after_quantity` | number | Stock quantity after the operation. | +| `cost` | number | Unit cost applied to the deduction. | +| `before_cost` | number | Stock cost before the operation. | +| `total_cost` | number | Total cost of the deducted quantity. | +| `operated_at` | string | When the operation was applied (YYYY-MM-DD HH:mm:ss). | +| `product` | object | Related product. Present even when the product was soft-deleted. | +| `stock` | object | Affected stock together with its storage. | + +##### `stock` + +| Field | Type | Description | +| --------- | ------ | -------------------------------------------- | +| `id` | number | Stock identifier. | +| `storage` | object | Storage the stock belongs to (`id`, `name`). | + +#### Notes + +* The endpoint returns only the receipt's own deductions (`operation_id = null`, `receipt_product_id != null`); inventory adjustments from other documents are not included. +* A `product` may be soft-deleted but is still returned so historical receipts remain fully reconcilable. +* Combine with [Get Receipt by ID](https://developer.clopos.com/docs/api-reference/v2/receipts/get-receipt-by-id) to map each `receipt_product_id` back to its sold line item. + +### List Receipts + +Source: + +`GET /v2/receipts` + +Retrieve all receipts with support for filters and sorting + +#### Purpose + +Speeds up your reconciliation flows by listing sales receipts by date, amount, or status. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/receipts +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Query Parameters + +- `` (integer): Page number for pagination (1-based). + +- `` (integer): Number of receipts per page. + +- `` (string): Start date of a `created_at` range, inclusive. Format: `YYYY-MM-DD`. Pair with `date[1]`. + +- `` (string): End date of a `created_at` range, inclusive. Format: `YYYY-MM-DD`. + +- `` (string): Field to sort by (e.g. `created_at`, `updated_at`, `closed_at`, `total`). Inspect the `sorts` array in the response to discover all sortable fields the API currently supports. + +- `` (integer): Sort direction: `1` = ascending, `-1` = descending. + +- `` (array[string]): + + Related resources to include in each receipt. Repeat with indexed brackets (e.g. `with[0]=receipt_products&with[1]=receipt_products.modificators`). Common values: + + * `receipt_products` — line items on each receipt + * `receipt_products.modificators` — modifiers applied to each line item + * `receipt_products.product.unit`, `receipt_products.product.station` — product relations + +- `` (array): Field-level filter tuples using PHP bracket notation: `filters[N][0]=field_name&filters[N][1]=value`. Stack filters by incrementing `N` (0-based). Commonly used with `status`, `sale_type_id`, `terminal_id`. + +#### Request Example + +```bash +# Basic request with filters +curl --location --globoff "https://integrations.clopos.com/open-api/v2/receipts?page=1&sort[0]=created_at&sort[1]=-1&limit=50&date[0]=2026-01-19&date[1]=2026-01-19" \ + -H "x-token: oauth_example_token" + +# With products and modifiers +curl --location --globoff "https://integrations.clopos.com/open-api/v2/receipts?page=1&sort[0]=created_at&sort[1]=-1&limit=50&date[0]=2026-01-19&date[1]=2026-01-19&with[0]=receipt_products.product.unit&with[1]=receipt_products.product.station&with[2]=receipt_products.modificators.modificator_group" \ + -H "x-token: oauth_example_token" +``` + +```javascript +const headers = { 'x-token': 'oauth_example_token' }; + +// Basic request with filters +const params = new URLSearchParams({ + 'page': '1', + 'sort[0]': 'created_at', + 'sort[1]': '-1', + 'limit': '50', + 'date[0]': '2026-01-19', + 'date[1]': '2026-01-19' +}); + +const response = await fetch( + `https://integrations.clopos.com/open-api/v2/receipts?${params}`, + { headers } +); +const receipts = await response.json(); + +// With products and modifiers +const paramsWithProducts = new URLSearchParams({ + 'page': '1', + 'sort[0]': 'created_at', + 'sort[1]': '-1', + 'limit': '50', + 'date[0]': '2025-08-12', + 'date[1]': '2025-08-18', + 'with[0]': 'receipt_products.product.unit', + 'with[1]': 'receipt_products.product.station', + 'with[2]': 'receipt_products.modificators.modificator_group' +}); + +const responseWithProducts = await fetch( + `https://integrations.clopos.com/open-api/v2/receipts?${paramsWithProducts}`, + { headers } +); +const receiptsWithProducts = await responseWithProducts.json(); +``` + +```python +import requests + +url = "https://integrations.clopos.com/open-api/v2/receipts" +headers = { + "x-token": "oauth_example_token", +} + +# Basic request with filters +params = { + "page": 1, + "sort[0]": "created_at", + "sort[1]": -1, + "limit": 50, + "date[0]": "2026-01-19", + "date[1]": "2026-01-19" +} + +response = requests.get(url, headers=headers, params=params) +receipts = response.json() + +# With products and modifiers +params_with_products = { + "page": 1, + "sort[0]": "created_at", + "sort[1]": -1, + "limit": 50, + "date[0]": "2025-08-12", + "date[1]": "2025-08-18", + "with[0]": "receipt_products.product.unit", + "with[1]": "receipt_products.product.station", + "with[2]": "receipt_products.modificators.modificator_group" +} + +response = requests.get(url, headers=headers, params=params_with_products) +receipts_with_products = response.json() +``` + +#### Response + +##### 200 OK — List of receipts + +```json +{ + "success": true, + "data": [ + { + "id": 1, + "venue_id": 1, + "cid": "96ab5d26-d6bb-4976-a6f8-9e8806ef6aa5", + "customer_id": null, + "sale_type_id": 2, + "source": "web", + "guests": 1, + "status": 2, + "order_status": "IN_PROGRESS", + "order_number": "006", + "lock": false, + "total": 33000, + "subtotal": 33000, + "discount_type": 0, + "discount_value": 0, + "discount_rate": 0, + "total_discount": 0, + "service_charge": 0, + "service_charge_value": 0, + "delivery_fee": 0, + "remaining": 0, + "i_tax": 0, + "e_tax": 0, + "total_tax": 0, + "payment_methods": [ + { + "id": 1, + "name": "Cash", + "amount": 33000 + } + ], + "fiscal_id": null, + "loyalty_type": null, + "loyalty_value": null, + "address": null, + "description": null, + "created_at": "2026-01-19 14:51:33", + "updated_at": "2026-01-19 15:07:49", + "closed_at": "2026-01-19 15:07:49", + "shift_date": "2026-01-19" + } + ], + "total": 1 +} +``` + +##### 400 Bad Request — Parameter error + +```json +{ + "success": false, + "error": "invalid_parameter", + "message": "sort[1] must be 1 or -1" +} +``` + +##### 401 Unauthorized — Missing header + +```json +{ + "success": false, + "error": "unauthorized", + "message": "Missing authentication headers" +} +``` + +#### Field Reference + +##### Receipt object + +| Field | Type | Description | +| ---------------------- | ------------ | ----------------------------------------------------------------------------------------------------------------- | +| `id` | number | Unique receipt identifier. | +| `cid` | string | Client-generated UUID for the receipt. | +| `venue_id` | number | Venue (location) the receipt belongs to. | +| `customer_id` | number\|null | Customer associated with the receipt. | +| `sale_type_id` | number | Sale type identifier (e.g., dine-in, delivery). | +| `source` | string | Origin of the receipt (e.g., `"web"`, `"pos"`). | +| `guests` | number | Number of guests on the receipt. | +| `status` | number | Receipt status: `1` = open, `2` = closed. | +| `order_status` | string | Order workflow status. One of: `NEW`, `SCHEDULED`, `IN_PROGRESS`, `READY`, `PICKED_UP`, `COMPLETED`, `CANCELLED`. | +| `order_number` | string\|null | External or display order number. | +| `lock` | boolean | Whether the receipt is locked from further changes. | +| `total` | number | Total amount collected. | +| `subtotal` | number | Subtotal before discounts, taxes, and fees. | +| `discount_type` | number | Discount type applied (0 = none). | +| `discount_value` | number | Discount amount or percentage value. | +| `discount_rate` | number | Effective discount rate. | +| `total_discount` | number | Total discount applied to the receipt. | +| `service_charge` | number | Service charge percentage. | +| `service_charge_value` | number | Calculated service charge amount. | +| `delivery_fee` | number | Delivery fee amount. | +| `remaining` | number | Outstanding balance (0 when fully paid). | +| `i_tax` | number | Inclusive tax amount. | +| `e_tax` | number | Exclusive tax amount. | +| `total_tax` | number | Total tax amount (inclusive + exclusive). | +| `payment_methods` | array | Payment breakdown. See [Payment method](https://developer.clopos.com/docs/common-objects#payment-method-in-receipts). | +| `fiscal_id` | string\|null | Fiscal receipt identifier for tax reporting. | +| `loyalty_type` | string\|null | Loyalty program type applied. | +| `loyalty_value` | number\|null | Loyalty discount or points value. | +| `address` | string\|null | Delivery address. | +| `description` | string\|null | Delivery or order notes. | +| `created_at` | string | Receipt creation time (YYYY-MM-DD HH:mm:ss). | +| `updated_at` | string | Last update time (YYYY-MM-DD HH:mm:ss). | +| `closed_at` | string\|null | Receipt close time (YYYY-MM-DD HH:mm:ss). | +| `shift_date` | string | Business day the receipt belongs to (YYYY-MM-DD). | + +See [Payment method](https://developer.clopos.com/docs/common-objects#payment-method-in-receipts) for the `payment_methods[]` structure. + +#### Notes + +* Use the `date[0]` and `date[1]` filters to restrict receipts to a date range (inclusive, YYYY-MM-DD). +* Sorting accepts multiple fields (`sort[0]`, `sort[1]`, etc.); directions must be `1` (ascending) or `-1` (descending). +* Pagination uses classic `page` and `limit` semantics; the default `limit` is 50. +* Combine `status`, `sale_type_id`, and date filters via the OpenAPI explorer when you need more granular reporting. +* The response also includes `time`, `timestamp`, `unix`, and `sorts` fields for diagnostics and discovering sortable fields; these are omitted from examples for brevity. + +### Update Receipt (after close) + +Source: + +`PATCH /v2/receipts/{id}` + +Update specific fields of an existing receipt + +#### Purpose + +Update specific fields of a receipt using the PATCH method. Only the provided fields will be updated; all other fields remain unchanged. + +**Important Notes:** + +* The PATCH method can update receipts even after they are closed (when `closed_at` is not null). +* Only limited fields can be updated via PATCH (see the field list below). + +#### HTTP Request + +```http +PATCH https://integrations.clopos.com/open-api/v2/receipts/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Path Parameters + +| Parameter | Type | Description | +| --------- | ------ | ------------------------------------------- | +| `id` | number | Unique identifier of the receipt to update. | + +#### Request Body + +Only the fields you want to update need to be included in the request body. Available updateable fields: + +| Field | Type | Description | +| -------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------- | +| `order_status` | string | Order status. Valid values: `"NEW"`, `"SCHEDULED"`, `"IN_PROGRESS"`, `"READY"`, `"PICKED_UP"`, `"COMPLETED"`, `"CANCELLED"`. | +| `order_number` | string | Order number identifier (e.g., `"RPO-00001"`). | +| `fiscal_id` | string | Fiscal receipt identifier. | +| `lock` | boolean | Lock status of the receipt (`true` or `false`). | + +#### Request Example + +```bash +curl --location --request PATCH 'https://integrations.clopos.com/open-api/v2/receipts/1' \ + --header 'Content-Type: application/json' \ + --header 'x-token: oauth_example_token' \ + --data '{ + "order_status": "NEW", + "order_number": "RPO-00001", + "fiscal_id": "Twrewr89fnscvj22", + "lock": false +}' +``` + +```javascript +const receiptId = 1; + +const response = await fetch(`https://integrations.clopos.com/open-api/v2/receipts/${receiptId}`, { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + 'x-token': 'oauth_example_token', + }, + body: JSON.stringify({ + order_status: 'NEW', + order_number: 'RPO-00001', + fiscal_id: 'Twrewr89fnscvj22', + lock: false + }) +}); + +const receipt = await response.json(); +``` + +```python +import requests + +receipt_id = 1 +url = f"https://integrations.clopos.com/open-api/v2/receipts/{receipt_id}" +headers = { + "Content-Type": "application/json", + "x-token": "oauth_example_token", +} +payload = { + "order_status": "NEW", + "order_number": "RPO-00001", + "fiscal_id": "Twrewr89fnscvj22", + "lock": False +} + +response = requests.patch(url, headers=headers, json=payload) +receipt = response.json() +``` + +#### Response + +##### 200 OK — Receipt Updated + +The response returns the full receipt data with updated fields: + +```json +{ + "success": true, + "data": { + "id": 1, + "venue_id": 1, + "cid": "96ab5d26-d6bb-4976-a6f8-9e8806ef6aa5", + "customer_id": null, + "sale_type_id": 2, + "source": "web", + "guests": 1, + "status": 2, + "order_status": "NEW", + "order_number": "RPO-00001", + "lock": false, + "total": 30000, + "subtotal": 30000, + "discount_type": 0, + "discount_value": 0, + "discount_rate": 0, + "total_discount": 0, + "service_charge": 0, + "service_charge_value": 0, + "delivery_fee": 0, + "remaining": 0, + "i_tax": 0, + "e_tax": 0, + "total_tax": 0, + "payment_methods": [ + { + "id": 1, + "name": "Cash", + "amount": 30000 + } + ], + "fiscal_id": "Twrewr89fnscvj22", + "loyalty_type": null, + "loyalty_value": null, + "address": null, + "description": null, + "created_at": "2026-01-19 14:51:33", + "updated_at": "2026-01-20 12:43:07", + "closed_at": "2026-01-19 15:07:49", + "shift_date": "2026-01-19" + }, + "message": "Operation completed successfully" +} +``` + +##### 404 Not Found — Receipt Not Found + +```json +{ + "success": false, + "error": "not_found", + "message": "Receipt not found" +} +``` + +##### 400 Bad Request — Validation Error + +```json +{ + "success": false, + "error": "validation_failed", + "message": "Invalid field values provided" +} +``` + +#### Field Reference + +##### Updateable Fields + +| Field | Type | Description | +| -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ | +| `order_status` | string | Current order status. Valid values: `"NEW"`, `"SCHEDULED"`, `"IN_PROGRESS"`, `"READY"`, `"PICKED_UP"`, `"COMPLETED"`, `"CANCELLED"`. | +| `order_number` | string | External order number or identifier. | +| `fiscal_id` | string | Fiscal receipt identifier used for tax reporting. | +| `lock` | boolean | If `true`, locks the receipt to prevent further modifications. | + +#### Notes + +* Only the fields provided in the request body will be updated; all other fields remain unchanged. +* The response includes the complete receipt object with all integrator-relevant fields, not just the updated ones. +* Only the specified fields (`order_status`, `order_number`, `fiscal_id`, `lock`) can be updated through this endpoint. +* Other receipt fields are read-only and cannot be modified via this API. +* This method can update receipts even after they are closed (when `closed_at` is not null). +* The response also includes `time`, `timestamp`, and `unix` fields for diagnostics; these are omitted from the example for brevity. + +## Sales + +### List Payment Methods + +Source: + +`GET /v2/payment-methods` + +Retrieve a list of all configured payment methods. + +This endpoint retrieves a list of all configured payment methods. + +Payment methods represent tender types (e.g., cash, card, wallet). They are used when closing receipts and reconciling totals. + +!!! note + The `status` object is a venue map. Its keys are `venue_id` strings and the + values indicate enablement at that venue: `1` = enabled, `0` = disabled. + For example, `status["1"] = 1` means this payment method is enabled for + venue `1`. + +**Used by** + +* [Close Receipt](https://developer.clopos.com/docs/api-reference/v2/receipts/close-receipt): map each tender to `payment_methods[]` + +#### Response Example + +```json +{ + "success": true, + "data": [ + { + "id": 1, + "name": "Cash", + "status": { + "1": 1, + "2": 1, + "3": 1 + }, + "split": 1, + "position": 0, + "customer_required": 0, + "is_system": 0, + "created_at": "2026-01-13T14:08:49.000000Z", + "updated_at": "2026-01-13T10:22:12.000000Z", + "balance": { + "id": 1, + "system_type": "CASH", + "name": "Kassa", + "type": "CASH" + }, + "service": null + }, + { + "id": 2, + "name": "Card", + "status": { + "1": 1, + "2": 1, + "3": 1 + }, + "split": 1, + "position": 0, + "customer_required": 0, + "is_system": 0, + "created_at": "2026-01-13T14:08:49.000000Z", + "updated_at": "2026-01-13T10:22:12.000000Z", + "balance": { + "id": 2, + "system_type": "CARD", + "name": "Kart", + "type": "CARD" + }, + "service": null + }, + { + "id": 3, + "name": "Customer Balance", + "status": { + "1": 0, + "2": 1, + "3": 1 + }, + "split": 1, + "position": 0, + "customer_required": 1, + "is_system": 0, + "created_at": "2026-01-13T14:08:49.000000Z", + "updated_at": "2026-01-13T10:22:12.000000Z", + "balance": null, + "service": null + }, + { + "id": 4, + "name": "Cashback", + "status": { + "1": 0, + "2": 0, + "3": 0 + }, + "split": 1, + "position": 0, + "customer_required": 1, + "is_system": 0, + "created_at": "2026-01-13T14:08:49.000000Z", + "updated_at": "2026-01-13T10:22:12.000000Z", + "balance": null, + "service": { + "name": "loyalty", + "check": [], + "payload": [] + } + } + ], + "total": 4 +} +``` + +#### Field Reference + +##### Payment Method Object + +| Field | Type | Description | +| ------------------- | ----------------- | ---------------------------------------------------------------------------------------------- | +| `id` | integer | Unique identifier for the payment method. | +| `name` | string | Display name of the payment method (e.g., "Cash", "Card"). | +| `status` | object | Map of `venue_id` (string) to `0`/`1` indicating whether this method is enabled at each venue. | +| `split` | integer | `1` if this payment method can be used for split payments, `0` otherwise. | +| `position` | integer | Display order position. | +| `customer_required` | integer | `1` if a customer must be attached to the transaction, `0` otherwise. | +| `is_system` | integer | `1` if this is a system-default payment method, `0` otherwise. | +| `created_at` | string | Creation timestamp (ISO 8601). | +| `updated_at` | string | Last update timestamp (ISO 8601). | +| `balance` | object (nullable) | Associated balance account, or `null` if none. See Balance object. | +| `service` | object (nullable) | External service integrated with this payment method (e.g., loyalty), or `null`. | + +##### Balance Object (nested in `balance`) + +| Field | Type | Description | +| ------------- | ------- | -------------------------------------------------- | +| `id` | integer | Balance account identifier. | +| `system_type` | string | System type of the balance (e.g., `CASH`, `CARD`). | +| `name` | string | Display name of the balance account. | +| `type` | string | Balance type (e.g., `CASH`, `CARD`). | + +### List Sale Types + +Source: + +`GET /v2/sale-types` + +Retrieve a list of all available sale types. + +This endpoint retrieves a list of all available sale types, such as In-store, Delivery, and Takeaway. + +Sale types represent the fulfillment channel for an order (e.g., dine-in, delivery, takeaway) and may determine service charge behavior. + +!!! note + The `status` object is a venue map. Its keys are `venue_id` strings and the + values indicate enablement at that venue: `1` = enabled, `0` = disabled. + For example, `status["1"] = 1` means this sale type is enabled for + venue `1`. + +**Used by** + +* [Create Order](https://developer.clopos.com/docs/api-reference/v2/orders/create-order): provide `payload.service.sale_type_id` and `payload.service.venue_id` + +#### Response Example + +```json +{ + "success": true, + "data": [ + { + "id": 1, + "name": "Yerinde", + "system_type": "IN", + "channel": "IN", + "status": { + "1": 1, + "2": 1, + "3": 1 + }, + "service_charge_rate": null, + "position": 0, + "media": [], + "created_at": "2026-01-13T14:08:49.000000Z", + "updated_at": "2026-01-13T10:22:12.000000Z" + }, + { + "id": 2, + "name": "Catdirilma", + "system_type": "DELIVERY", + "channel": "DELIVERY", + "status": { + "1": 1, + "2": 1, + "3": 1 + }, + "service_charge_rate": null, + "position": 0, + "media": [ + { + "urls": { + "original": "https://cdn.clopos.com/_clopos/delivery.png", + "large": "https://cdn.clopos.com/_clopos/delivery.png" + } + } + ], + "created_at": "2026-01-13T14:08:49.000000Z", + "updated_at": "2026-01-13T10:22:12.000000Z" + }, + { + "id": 3, + "name": "Takeaway", + "system_type": "TAKEAWAY", + "channel": "TAKEAWAY", + "status": { + "1": 1, + "2": 1, + "3": 1 + }, + "service_charge_rate": null, + "position": 0, + "media": [ + { + "urls": { + "original": "https://cdn.clopos.com/_clopos/takeaway.png", + "large": "https://cdn.clopos.com/_clopos/takeaway.png" + } + } + ], + "created_at": "2026-01-13T14:08:49.000000Z", + "updated_at": "2026-01-13T10:22:12.000000Z" + } + ], + "total": 3 +} +``` + +#### Field Reference + +##### Sale Type Object + +| Field | Type | Description | +| --------------------- | ----------------- | ------------------------------------------------------------------------------------------------- | +| `id` | integer | Unique identifier for the sale type. | +| `name` | string | Display name of the sale type (e.g., "In-store", "Delivery"). | +| `system_type` | string | System-defined type identifier: `IN`, `DELIVERY`, `TAKEAWAY`. | +| `channel` | string | Sales channel this type belongs to. | +| `status` | object | Map of `venue_id` (string) to `0`/`1` indicating whether this sale type is enabled at each venue. | +| `service_charge_rate` | number (nullable) | Service charge rate associated with this sale type, or `null` if none. | +| `position` | integer | Display order position. | +| `media` | array | Image attachments. See [Media object](https://developer.clopos.com/docs/common-objects#media). | +| `created_at` | string | Creation timestamp (ISO 8601). | +| `updated_at` | string | Last update timestamp (ISO 8601). | + +## Stations + +### Get Station by ID + +Source: + +`GET /v2/stations/{id}` + +Retrieve a specific preparation or service station + +#### Purpose + +Verifies the status and printing capabilities of a single station, such as a kitchen, bar, or custom station. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/stations/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Request Example + +```bash +curl -X GET "https://integrations.clopos.com/open-api/v2/stations/1" \ + -H "x-token: oauth_example_token" \ +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/stations/1', { + headers: { + 'x-token': 'oauth_example_token', + } +}); + +const station = await response.json(); +``` + +```python +import requests + +url = "https://integrations.clopos.com/open-api/v2/stations/1" +headers = { + "x-token": "oauth_example_token", +} + +response = requests.get(url, headers=headers) +station = response.json() +``` + +#### Response + +##### 200 OK — Station found + +```json +{ + "success": true, + "data": { + "id": 1, + "name": "Kitchen", + "status": 1, + "type": 1, + "printable": 1, + "created_at": "2026-01-13T14:08:49.000000Z", + "updated_at": "2026-01-13T14:08:49.000000Z" + } +} +``` + +##### 404 Not Found — Station does not exist + +```json +{ + "success": false, + "error": "resource_not_found", + "message": "Station not found" +} +``` + +#### Field Reference + +##### Station object + +| Field | Type | Description | +| ------------ | ------- | ---------------------------------------------------- | +| `id` | integer | Station identifier. | +| `name` | string | Station name. | +| `status` | integer | `1` = active, `0` = inactive. | +| `type` | integer | Station type. `1` = kitchen, `0` = other. | +| `printable` | integer | `1` if the station can print tickets, `0` otherwise. | +| `created_at` | string | Creation timestamp (ISO 8601). | +| `updated_at` | string | Last update timestamp (ISO 8601). | + +#### Notes + +* The station ID is used for product and printer mapping on the POS side; verify the current restaurant flow before making changes. +* Stations with `printable=0` are designed only for screen notifications or digital preparation processes. +* If a station is not found, it returns `404`; selecting a fallback station on the client side or showing a remapping screen to the user provides a good experience. + +### List Stations + +Source: + +`GET /v2/stations` + +Retrieve all preparation and service stations + +#### Purpose + +Allows you to check printer, reminder, and status information by retrieving all stations in your POS and kitchen flows in a single call. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/stations +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Query Parameters + +- `` (integer): Filter by station status (`1` = active, `0` = inactive). + +- `` (boolean): Filter stations that can redirect to a printer. + +- `` (integer): Page number for pagination. + +- `` (integer): Number of stations to return (1-200). + +#### Request Example + +```bash +curl -X GET "https://integrations.clopos.com/open-api/v2/stations?status=1" \ + -H "x-token: oauth_example_token" \ +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/stations?status=1', { + headers: { + 'x-token': 'oauth_example_token', + } +}); + +const stations = await response.json(); +``` + +```python +import requests + +url = "https://integrations.clopos.com/open-api/v2/stations" +headers = { + "x-token": "oauth_example_token", +} +params = { + "status": 1, + "limit": 50 +} + +response = requests.get(url, headers=headers, params=params) +stations = response.json() +``` + +#### Response + +##### 200 OK — List of stations + +```json +{ + "success": true, + "data": [ + { + "id": 1, + "name": "Kitchen", + "status": 1, + "type": 1, + "printable": 1, + "created_at": "2026-01-13T14:08:49.000000Z", + "updated_at": "2026-01-13T14:08:49.000000Z" + }, + { + "id": 2, + "name": "Bar", + "status": 1, + "type": 0, + "printable": 1, + "created_at": "2026-01-13T14:08:49.000000Z", + "updated_at": "2026-01-13T14:08:49.000000Z" + }, + { + "id": 3, + "name": "Tandir", + "status": 1, + "type": 0, + "printable": 0, + "created_at": "2026-01-13T14:36:51.000000Z", + "updated_at": "2026-01-13T14:36:51.000000Z" + } + ], + "total": 3 +} +``` + +##### 401 Unauthorized — Authorization missing + +```json +{ + "success": false, + "error": "unauthorized", + "message": "Missing authentication headers" +} +``` + +#### Field Reference + +##### Station object + +| Field | Type | Description | +| ------------ | ------- | ---------------------------------------------------- | +| `id` | integer | Station identifier. | +| `name` | string | Station name. | +| `status` | integer | `1` = active, `0` = inactive. | +| `type` | integer | Station type. `1` = kitchen, `0` = other. | +| `printable` | integer | `1` if the station can print tickets, `0` otherwise. | +| `created_at` | string | Creation timestamp (ISO 8601). | +| `updated_at` | string | Last update timestamp (ISO 8601). | + +#### Notes + +* Stations with `printable=0` are designed only for screen notifications or digital preparation processes. +* The active/inactive status of stations affects product routing on the POS side; inactive stations are not assigned to new orders. +* Adjust pagination parameters (`page`, `limit`) for performance in large restaurant chains; it is generally not necessary for a single branch. + +## Users + +### Get User by ID + +Source: + +`GET /v2/users/{id}` + +Retrieve a specific user by their unique identifier. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/users/{id} +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Path Parameters + +- `` (integer): The unique identifier of the user. + +#### Request Example + +```bash +curl --location 'https://integrations.clopos.com/open-api/v2/users/1' \ + --header 'Content-Type: application/json' \ + --header 'Accept: application/json' +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/users/1', { + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json' + } +}); +``` + +```python +import requests + +url = 'https://integrations.clopos.com/open-api/v2/users/1' +headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json' +} + +response = requests.get(url, headers=headers) +print(response.json()) +``` + +#### Response + +```json +{ + "success": true, + "data": { + "id": 1, + "email": "vitrin@clopos.com", + "username": "Clopos Test", + "first_name": "Clopos", + "last_name": "Test", + "mobile_number": null, + "owner": 1, + "status": true, + "created_at": "2026-01-13T14:08:48.000000Z", + "updated_at": "2026-02-20T15:07:02.000000Z" + } +} +``` + +*** + +#### Field Reference + +##### User Object + +| Field | Type | Description | +| --------------- | ----------------- | ---------------------------------------------------- | +| `id` | integer | Unique user identifier. | +| `email` | string (nullable) | Email address associated with the user. | +| `username` | string | Display name shown in the POS. | +| `first_name` | string (nullable) | First name of the user. | +| `last_name` | string (nullable) | Last name of the user. | +| `mobile_number` | string (nullable) | Mobile phone number. | +| `owner` | integer | `1` if the user owns the brand, otherwise `0`. | +| `status` | boolean | Indicates whether the user account is active. | +| `created_at` | string | Timestamp when the user was created (ISO 8601). | +| `updated_at` | string | Timestamp when the user was last updated (ISO 8601). | + +### List Users + +Source: + +`GET /v2/users` + +Retrieve a list of active Clopos users + +Use this endpoint to inspect staff accounts, roles, and access levels across your venues. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/users +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Request Example + +```bash +curl --location 'https://integrations.clopos.com/open-api/v2/users' \ + --header 'Content-Type: application/json' \ + --header 'Accept: application/json' +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/users', { + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json' + } +}); +``` + +```python +import requests + +url = 'https://integrations.clopos.com/open-api/v2/users' +headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json' +} + +response = requests.get(url, headers=headers) +print(response.json()) +``` + +#### Response + +```json +{ + "success": true, + "data": [ + { + "id": 1, + "email": "vitrin@clopos.com", + "username": "Clopos Test", + "first_name": "Clopos", + "last_name": "Test", + "mobile_number": null, + "owner": 1, + "status": true, + "created_at": "2026-01-13T14:08:48.000000Z", + "updated_at": "2026-02-20T15:07:02.000000Z" + }, + { + "id": 3, + "email": null, + "username": "Cashier", + "first_name": null, + "last_name": null, + "mobile_number": null, + "owner": 0, + "status": true, + "created_at": "2026-01-13T14:08:49.000000Z", + "updated_at": "2026-03-12T16:32:36.000000Z" + } + ], + "total": 3 +} +``` + +*** + +#### Field Reference + +##### User Object + +| Field | Type | Description | +| --------------- | ----------------- | ---------------------------------------------------- | +| `id` | integer | Unique user identifier. | +| `email` | string (nullable) | Email address associated with the user. | +| `username` | string | Display name shown in the POS. | +| `first_name` | string (nullable) | First name of the user. | +| `last_name` | string (nullable) | Last name of the user. | +| `mobile_number` | string (nullable) | Mobile phone number. | +| `owner` | integer | `1` if the user owns the brand, otherwise `0`. | +| `status` | boolean | Indicates whether the user account is active. | +| `created_at` | string | Timestamp when the user was created (ISO 8601). | +| `updated_at` | string | Timestamp when the user was last updated (ISO 8601). | + +## Venues + +### List Venues + +Source: + +`GET /v2/venues` + +Retrieve a list of all venues (locations). + +#### Purpose + +Allows you to quickly retrieve active branches connected to your brand to initiate location-based operations. + +#### HTTP Request + +```http +GET https://integrations.clopos.com/open-api/v2/venues +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Request Example + +```bash +curl -X GET "https://integrations.clopos.com/open-api/v2/venues" \ + -H "x-token: oauth_example_token" \ +``` + +```javascript +const response = await fetch('https://integrations.clopos.com/open-api/v2/venues', { + headers: { + 'x-token': 'oauth_example_token', + } +}); + +const venues = await response.json(); +``` + +```python +import requests + +url = "https://integrations.clopos.com/open-api/v2/venues" +headers = { + "x-token": "oauth_example_token", +} + +response = requests.get(url, headers=headers) +venues = response.json() +``` + +#### Response + +##### 200 OK — List of branches + +```json +{ + "success": true, + "data": [ + { + "id": 1, + "name": "Main", + "is_main": 1, + "media": [] + }, + { + "id": 2, + "name": "Baku", + "is_main": 0, + "media": [] + }, + { + "id": 3, + "name": "Masally", + "is_main": 0, + "media": [] + } + ] +} +``` + +##### 401 Unauthorized — Missing header + +```json +{ + "success": false, + "error": "unauthorized", + "message": "Missing authentication headers" +} +``` + +#### Field Reference + +##### Branch object + +| Field | Type | Description | +| --------- | ------- | ------------------------------------------------------------------ | +| `id` | integer | Branch ID. | +| `name` | string | Branch name. | +| `is_main` | integer | `1` if this is the primary branch, `0` otherwise. | +| `media` | array | Image attachments. See [Media object](https://developer.clopos.com/docs/common-objects#media). | + +#### Notes + +* This endpoint returns all branches you have access to; use client-side logic to filter the result set. +* Use `is_main` to identify the primary branch in multi-location setups. +* Although the response size is small, client-side caching is recommended for large brands. + +## Waiter Call + +### Waiter Call + +Source: + +`POST /v2/waiter-call` + +Trigger a waiter call or a payment request for a table + +#### Purpose + +Allows integrators to notify restaurant staff at a specific table — either to request a waiter or to initiate a payment with a chosen payment method. + +#### HTTP Request + +```http +POST https://integrations.clopos.com/open-api/v2/waiter-call +``` + +!!! warning + This endpoint requires authentication. Include your JWT in the `x-token` header. See [Authentication](https://developer.clopos.com/docs/authentication) for how to obtain a token and [Errors](https://developer.clopos.com/docs/errors) for error responses. + +#### Module Requirement + +!!! warning + This endpoint requires the `restaurant_emenu` module to be enabled for your brand. Requests made without this module active will return the standard "module not available" error. + +#### Request Body + +- `` (integer): The ID of the table for which the call is being triggered. Must correspond to an existing table in the venue. + +- `` (string): + + The type of call to trigger. Accepted values: + + * `WAITER` — notify staff that a waiter is needed at the table + * `PAY` — request payment for the table + +- `` (integer): + + The payment method ID to use when `type` is `PAY`. Must be the default **CASH** or **CARD** payment method configured for the venue. + + +!!! note + `payment_method` is required when `type` is `PAY` and must not be sent for `type` `WAITER`. + +#### Request Example + +```bash +curl --location 'https://integrations.clopos.com/open-api/v2/waiter-call' \ + -H 'x-token: oauth_example_token' \ + -H 'Content-Type: application/json' \ + -d '{ + "table_id": 5, + "type": "WAITER" + }' +``` + +```bash +curl --location 'https://integrations.clopos.com/open-api/v2/waiter-call' \ + -H 'x-token: oauth_example_token' \ + -H 'Content-Type: application/json' \ + -d '{ + "table_id": 5, + "type": "PAY", + "payment_method": 1 + }' +``` + +```javascript +// WAITER call +const response = await fetch('https://integrations.clopos.com/open-api/v2/waiter-call', { + method: 'POST', + headers: { + 'x-token': 'oauth_example_token', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + table_id: 5, + type: 'WAITER' + }) +}); + +// PAY call +const payResponse = await fetch('https://integrations.clopos.com/open-api/v2/waiter-call', { + method: 'POST', + headers: { + 'x-token': 'oauth_example_token', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + table_id: 5, + type: 'PAY', + payment_method: 1 + }) +}); + +const data = await response.json(); +``` + +```python +import requests + +url = "https://integrations.clopos.com/open-api/v2/waiter-call" +headers = { + "x-token": "oauth_example_token", + "Content-Type": "application/json" +} + +# WAITER call +payload = { + "table_id": 5, + "type": "WAITER" +} + +# PAY call +# payload = { +# "table_id": 5, +# "type": "PAY", +# "payment_method": 1 +# } + +response = requests.post(url, headers=headers, json=payload) +result = response.json() +``` + +#### Response + +##### 200 OK — Call triggered successfully + +```json +{ + "success": true +} +``` + +##### 400 Bad Request — Validation or creation failure + +Returned when the request body is invalid (e.g. unknown `table_id`, unsupported `type`, missing `payment_method` for a `PAY` call, or invalid payment method ID). + +```json +{ + "success": false +} +``` diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index 7f66686..0b8bc56 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -124,6 +124,7 @@ nav: - Response: integrations/clopos/api-reference/response.md - Enums: integrations/clopos/api-reference/enums.md - integrations/clopos/api-reference/helper-functions.md + - Official Documentation: integrations/clopos/official/api.md # Private section (separate build, password-protected): see docs/private.yml - E-Customs (private): - E-Customs (AZ): /private/ecustoms/ diff --git a/docs/en/partial.yml b/docs/en/partial.yml deleted file mode 100644 index 905f368..0000000 --- a/docs/en/partial.yml +++ /dev/null @@ -1,9 +0,0 @@ -Clopos: - - "integrations/clopos/index.md" - - "integrations/clopos/env.md" - - API Reference: - - API Client: "integrations/clopos/api-reference/client.md" - - Schemas: - - Response: "integrations/clopos/api-reference/response.md" - - Enums: "integrations/clopos/api-reference/enums.md" - - "integrations/clopos/api-reference/helper-functions.md" diff --git a/packages/lsim/README.md b/packages/lsim/README.md index 5fc8e72..a52960e 100644 --- a/packages/lsim/README.md +++ b/packages/lsim/README.md @@ -20,7 +20,7 @@ ## Rəsmi Dokumentasiya (v2024.11.22) -[İngliscə](https://mmzeynalli.notion.site/LSIM-1974f14f727e8029a3f5f9e4e556afe3?pvs=74) +[İngliscə](https://integrify.mmzeynalli.dev/integrations/lsim/official/api/) ## Əsas özəlliklər diff --git a/packages/lsim/src/integrify/lsim/__init__.py b/packages/lsim/src/integrify/lsim/__init__.py index bab14ef..a312a39 100644 --- a/packages/lsim/src/integrify/lsim/__init__.py +++ b/packages/lsim/src/integrify/lsim/__init__.py @@ -1,7 +1,7 @@ """ Dokumentasiya: -EN: https://mmzeynalli.notion.site/LSIM-1974f14f727e8029a3f5f9e4e556afe3?pvs=74 +EN: https://integrify.mmzeynalli.dev/integrations/lsim/official/api/ """ from .bulk.client import LSIMBulkSMSAsyncClient, LSIMBulkSMSClient, LSIMBulkSMSClientClass