├── src
├── server
│ ├── index.ts
│ └── app.ts
├── utils
│ ├── generateOperationID.ts
│ ├── logger.ts
│ └── validateParameters.ts
├── routes
│ ├── ProductsStock
│ │ └── index.ts
│ ├── Public
│ │ └── index.ts
│ ├── Device
│ │ └── index.ts
│ └── User
│ │ └── index.ts
└── controllers
│ ├── ProductsStock
│ └── index.ts
│ ├── Device
│ ├── device.types.ts
│ └── index.ts
│ ├── Public
│ └── index.ts
│ └── User
│ └── index.ts
├── .dockerignore
├── tsconfig.json
├── .gitignore
├── Dockerfile
├── package.json
├── TODO.md
├── LICENSE
├── README.md
└── swagger
├── Public-1.json
└── User-1.json
/src/server/index.ts:
--------------------------------------------------------------------------------
1 | import app from './app';
2 | import logger from '../utils/logger';
3 |
4 | const PORT = process.env.PORT || 3000;
5 |
6 | app.listen(PORT, () => {
7 | logger.info(`Zimra FDMS Mock Server is running on port ${PORT}`);
8 | });
9 |
--------------------------------------------------------------------------------
/src/utils/generateOperationID.ts:
--------------------------------------------------------------------------------
1 | const generateOperationID = (): string => {
2 | const randomPart = Math.random().toString(36).substring(2, 10).toUpperCase();
3 | const timestamp = Date.now().toString(36).toUpperCase();
4 | return `0HMPH${randomPart}${timestamp}`.substring(0, 60);
5 | };
6 |
7 |
8 | export default generateOperationID;
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | # Version control
2 | .git
3 | .gitignore
4 |
5 | # Dependencies
6 | node_modules
7 | npm-debug.log
8 |
9 | # Build output
10 | dist
11 |
12 | # Environment variables
13 | .env
14 | .env.*
15 |
16 | # Development files
17 | README.md
18 | .vscode
19 | .idea
20 | *.md
21 | *.log
22 |
23 | # Docker files
24 | Dockerfile
25 | .dockerignore
26 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "module": "commonjs",
5 | "outDir": "./dist",
6 | "rootDir": "./src",
7 | "strict": true,
8 | "esModuleInterop": true,
9 | "skipLibCheck": true,
10 | "forceConsistentCasingInFileNames": true
11 | },
12 | "include": ["src/**/*"],
13 | "exclude": ["node_modules"]
14 | }
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | node_modules/
3 | npm-debug.log
4 | yarn-debug.log
5 | yarn-error.log
6 |
7 | # Build output
8 | dist/
9 | build/
10 |
11 | # Environment variables
12 | .env
13 | .env.local
14 | .env.*.local
15 |
16 | # IDE specific files
17 | .idea/
18 | .vscode/
19 | *.swp
20 | *.swo
21 |
22 | # OS specific files
23 | .DS_Store
24 | Thumbs.db
25 |
26 | # Logs
27 | logs/
28 | *.log
29 |
--------------------------------------------------------------------------------
/src/routes/ProductsStock/index.ts:
--------------------------------------------------------------------------------
1 | import { Router } from 'express';
2 | import * as productsStockController from '../../controllers/ProductsStock';
3 |
4 | const router = Router();
5 |
6 | // Add your products stock routes here
7 | // Example: router.get('/', productsStockController.getAllProducts);
8 |
9 |
10 | router.get('/v1/:deviceID/Search', productsStockController.getProductsStock);
11 |
12 | export { router as default };
13 |
--------------------------------------------------------------------------------
/src/utils/logger.ts:
--------------------------------------------------------------------------------
1 | import pino from 'pino';
2 |
3 | const transport = pino.transport({
4 | target: 'pino-pretty',
5 | options: {
6 | colorize: true,
7 | levelFirst: true,
8 | translateTime: 'yyyy-mm-dd HH:MM:ss',
9 | },
10 | });
11 |
12 | const logger = pino({
13 | level: process.env.LOG_LEVEL || 'info',
14 | base: {
15 | env: process.env.NODE_ENV || 'development',
16 | },
17 | }, transport);
18 |
19 | export default logger;
20 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # Use Node.js LTS version as the base image
2 | FROM node:18-alpine
3 |
4 | # Create app directory
5 | WORKDIR /usr/src/app
6 |
7 | # Copy package files
8 | COPY package*.json ./
9 |
10 | # Install dependencies
11 | RUN npm install
12 |
13 | # Copy source code
14 | COPY . .
15 |
16 | # Build TypeScript code
17 | RUN npm run build
18 |
19 | # Expose the port the app runs on
20 | EXPOSE 3000
21 |
22 | # Command to run the application
23 | CMD ["npm", "start"]
24 |
--------------------------------------------------------------------------------
/src/routes/Public/index.ts:
--------------------------------------------------------------------------------
1 | import { Router } from 'express';
2 |
3 | // @ts-ignore
4 | import * as publicController from '../../controllers/Public';
5 |
6 | const router = Router();
7 |
8 | router.post('/v1/:deviceID/RegisterDevice', publicController.registerDevice);
9 | router.get('/v1/GetServerCertificate', publicController.getServerCertificate);
10 | router.post('/v1/:deviceID/VerifyTaxpayerInformation', publicController.verifyTaxpayerInformation);
11 |
12 | export { router as default };
13 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "zimra-fdms-mock-server",
3 | "version": "1.0.0",
4 | "description": "ZIMRA FDMS Mock Server",
5 | "main": "dist/server/index.js",
6 | "scripts": {
7 | "start": "node dist/server/index.js",
8 | "dev": "nodemon src/server/index.ts",
9 | "build": "tsc",
10 | "test": "echo \"Error: no test specified\" && exit 1"
11 | },
12 | "keywords": [],
13 | "author": "",
14 | "license": "ISC",
15 | "dependencies": {
16 | "@types/express": "^4.17.17",
17 | "@types/node": "^20.5.0",
18 | "express": "^4.18.2",
19 | "nodemon": "^3.0.1",
20 | "pino": "^9.6.0",
21 | "pino-pretty": "^13.0.0",
22 | "ts-node": "^10.9.1",
23 | "typescript": "^5.1.6"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 | # Todo
2 | ✅ Device endpoints
3 | ✅ Public endpoints
4 | ✅ User endpoints
5 | ✅ ProductsStock endpoints
6 | ⏳ Make mock server as realistic as possible
7 |
8 |
9 | ## Realism
10 |
11 | ⏳ Mock expired certificate response at middleware level
12 | ⏳ Mock server error response at middleware level
13 | ⏳ Add realistic token
14 | ⏳ Implement realistic device check
15 | ⏳ Implement realistic certificate check
16 |
17 | ### More research needed
18 | ⏳ Implement realistic user check (maybe not necessary) {use sqlite here}
19 | ⏳ Implement realistic products stock check (maybe not necessary) {use sqlite here}
20 | ⏳ Implement realistic day check (maybe not necessary) {use sqlite here}
21 |
22 |
--------------------------------------------------------------------------------
/src/utils/validateParameters.ts:
--------------------------------------------------------------------------------
1 | export const checkDeviceID = (id: number): boolean => {
2 |
3 | try {
4 | const idNumber = Number(id);
5 | if (isNaN(idNumber) || idNumber <= 0 || idNumber >= 10000000000 || String(idNumber).length !== String(id).length) {
6 | return false;
7 | }
8 | return true;
9 | } catch (error) {
10 | return false;
11 | }
12 | };
13 |
14 | export const checkActivationKey = (key: string): boolean => {
15 | if (typeof key !== 'string' || key.length > 8 || key.length === 0) {
16 | return false;
17 | }
18 | return true;
19 | };
20 |
21 | export const checkDeviceSerialNo = (serialNo: string): boolean => {
22 | if (typeof serialNo !== 'string' || serialNo.length > 20 || serialNo.length === 0) {
23 | return false;
24 | }
25 | return true;
26 | };
27 |
28 |
--------------------------------------------------------------------------------
/src/routes/Device/index.ts:
--------------------------------------------------------------------------------
1 | import { Router } from 'express';
2 |
3 | // @ts-ignore
4 |
5 | import * as deviceController from '../../controllers/Device';
6 |
7 | const router = Router();
8 |
9 | router.get('/v1/:deviceID/GetConfig', deviceController.getConfig);
10 | router.get('/v1/:deviceID/GetStatus', deviceController.getStatus);
11 | router.post('/v1/:deviceID/OpenDay', deviceController.openDay);
12 | router.post('/v1/:deviceID/CloseDay', deviceController.closeDay);
13 | router.post('/v1/:deviceID/IssueCertificate', deviceController.issueCertificate);
14 | router.post('/v1/:deviceID/SubmitReciept', deviceController.submitReciept);
15 | router.post('/v1/:deviceID/Ping', deviceController.ping);
16 | router.post('/v1/:deviceID/SubmitFile', deviceController.submitFile);
17 | router.get('/v1/:deviceID/SubmittedFileList', deviceController.submittedFileList);
18 |
19 |
20 | export { router as default };
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 Takunda Madechangu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/src/routes/User/index.ts:
--------------------------------------------------------------------------------
1 | import { Router } from 'express';
2 | import * as userController from '../../controllers/User';
3 |
4 | const router = Router();
5 |
6 | // Add your user routes here
7 | // Example: router.get('/', userController.getAllUsers);
8 |
9 |
10 | router.get('/v1/:deviceID/GetUsersList', userController.getUsersList);
11 | router.post('/v1/:deviceID/SendSecurityCodeToTaxpayer', userController.sendSecurityCodeToTaxpayer);
12 | router.post('/v1/:deviceID/CreateUser', userController.createUser);
13 | router.post('/v1/:deviceID/Login', userController.loginUser);
14 | router.post('/v1/:deviceID/SendSecurityCodeToUserPhone', userController.sendSecurityCodeToUserPhone);
15 | router.post('/v1/:deviceID/SendSecurityCodeToUserEmail', userController.sendSecurityCodeToUserEmail);
16 | router.post('/v1/:deviceID/ConfirmUser', userController.confirmUser);
17 | router.post('/v1/:deviceID/ChangePassword', userController.changePassword);
18 | router.post('/v1/:deviceID/ResetPassword', userController.resetPassword);
19 | router.post('/v1/:deviceID/ConfirmContact', userController.confirmContact);
20 | router.post('/v1/:deviceID/Update', userController.update);
21 | router.post('/v1/:deviceID/ConfirmPasswordReset', userController.confirmPasswordReset);
22 |
23 |
24 | export { router as default };
25 |
--------------------------------------------------------------------------------
/src/server/app.ts:
--------------------------------------------------------------------------------
1 | import express, { Application } from 'express';
2 | import deviceRoutes from '../routes/Device';
3 | import publicRoutes from '../routes/Public';
4 | import userRoutes from '../routes/User';
5 | import productsStockRoutes from '../routes/ProductsStock';
6 | import logger from '../utils/logger';
7 |
8 | class App {
9 | public app: Application;
10 |
11 | constructor() {
12 | this.app = express();
13 | this.config();
14 | this.routes();
15 | }
16 |
17 | private config(): void {
18 | // Log all requests
19 | this.app.use((req, res, next) => {
20 | logger.info({
21 | method: req.method,
22 | url: req.url,
23 | query: req.query,
24 | body: req.body,
25 | }, 'Incoming request');
26 | next();
27 | });
28 |
29 | this.app.use(express.json());
30 | this.app.use(express.urlencoded({ extended: true }));
31 | }
32 |
33 | private routes(): void {
34 | this.app.use('/Device', deviceRoutes);
35 | this.app.use('/Public', publicRoutes);
36 | this.app.use('/User', userRoutes);
37 | this.app.use('/ProductsStock', productsStockRoutes);
38 | }
39 | }
40 |
41 | export default new App().app;
42 |
--------------------------------------------------------------------------------
/src/controllers/ProductsStock/index.ts:
--------------------------------------------------------------------------------
1 | import { Request, Response } from 'express';
2 | import generateOperationID from '../../utils/generateOperationID';
3 |
4 |
5 | interface ProductsStockGetListDto {
6 | hsCode: string;
7 | goodName: string;
8 | quantity: number;
9 | taxPayerId: number;
10 | taxPayerName: string;
11 | taxPayerTIN: string;
12 | branchId?: number;
13 | branchName?: string;
14 | }
15 |
16 | export const getProductsStock = async (req: Request, res: Response) => {
17 | try {
18 | const {
19 | HsCode, GoodName, Sort, Order, Offset, Limit, Operator, DeviceModelName, DeviceModelVersion
20 | } = req.query;
21 |
22 | const { deviceID } = req.params;
23 |
24 | console.log('Received parameters:', req.query);
25 |
26 | const offset = parseInt(Offset as string);
27 | const limit = parseInt(Limit as string);
28 |
29 | if (isNaN(offset) || isNaN(limit)) {
30 | return res.status(400).json({
31 | "type": "https://httpstatuses.io/422",
32 | "title": "Bad request",
33 | "status": 400,
34 | "detail": "Offset and Limit must be integers"
35 | });
36 | }
37 |
38 | // Example of interacting with a database or service
39 | const products: ProductsStockGetListDto[] = [
40 | {
41 | hsCode: '12345678',
42 | goodName: 'Sample Product',
43 | quantity: 100,
44 | taxPayerId: 1,
45 | taxPayerName: 'Tax Payer 1',
46 | taxPayerTIN: 'TIN12345',
47 | },
48 | // Add more mock data if needed
49 | ]
50 |
51 | if (deviceID === 'invalid' || deviceID === '0') {
52 | return res.status(404).json({
53 | "type": "https://httpstatuses.io/422",
54 | "title": "Unprocessable Entity",
55 | "status": 422,
56 | "detail": "Device fiscal day status must be FiscalDayClosed"
57 | });
58 | }
59 |
60 |
61 | res.status(200).json({
62 | total: products.length, // Assuming the total length here, or use a count query in DB
63 | rows: products
64 | });
65 | } catch (error) {
66 | console.error(error);
67 | res.status(500).json({
68 | "type": "https://httpstatuses.io/500",
69 | "title": "Server error",
70 | "status": 500,
71 | "operationID": generateOperationID()
72 | });
73 | }
74 | };
75 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ZIMRA FDMS Mock Server 🧾
2 |
3 | This is a mock server designed to simulate requests and responses as specified in the ZIMRA FDMS API documentation: https://fdmsapitest.zimra.co.zw/swagger/index.html
4 |
5 |
6 | > [!NOTE]
7 | > This mock server is particularly useful for developers who do not have immediate access to a fiscalized ID. However, please note that it is recommended to test with the original server whenever possible, as the responses may differ from those provided by this mock implementation.
8 |
9 | ## Stack
10 |
11 | - Node.js
12 | - Express
13 | - TypeScript
14 | - Docker
15 |
16 | ## Installation
17 |
18 | 1. Clone the repository:
19 | ```sh
20 | git clone https://github.com/takumade/zimra-fdms-mock-server.git
21 | cd zimra-fdms-mock-server
22 | ```
23 |
24 | 2. Install dependencies:
25 | - Using npm/yarn/pnpm:
26 | ```sh
27 | npm install
28 | ```
29 |
30 | 3. Start the server:
31 | - Using npm/yarn/pnpm:
32 | ```sh
33 | npm start
34 | ```
35 |
36 | NB: In place of `npm` you can use `yarn`, or `pnpm`.
37 |
38 | NB: The server will start running on `http://localhost:3000`.
39 |
40 |
41 | ## Deploying
42 |
43 | ### Docker
44 |
45 | To deploy the ZIMRA FDMS Mock Server using Docker, follow these steps:
46 |
47 | 1. Ensure Docker is installed on your system.
48 | 2. Navigate to the project root directory.
49 | 3. Build and run the Docker container:
50 |
51 | ```sh
52 | # Build the Docker image
53 | docker build -t zimra-mock-server .
54 |
55 | # Run the container
56 | docker run -p 3000:3000 zimra-mock-server
57 | ```
58 |
59 | The server will be accessible at `http://localhost:3000`.
60 |
61 |
62 |
63 | ### Live Endpoint
64 |
65 | You can access the live endpoint at:
66 |
67 | [https://zimra-fdms-mock-server.onrender.com](https://zimra-fdms-mock-server.onrender.com)
68 |
69 |
70 | > [!NOTE]
71 | > While this runs on a free tier and won't dip into my pocket, please don't abuse it.
72 |
73 | ## Contribution
74 | This project is open source and contributions are welcome. Please fork the repository and submit pull requests.
75 |
76 | > [!NOTE]
77 | > Given that it's a mock server, contributions are most welcome in the form of bug fixes and realism enhancements.
78 |
79 | ### Todo
80 | ✅ Device endpoints
81 | ✅ Public endpoints
82 | ✅ User endpoints
83 | ✅ ProductsStock endpoints
84 | ⏳ Make mock server as realistic as possible
85 |
86 |
87 | > [!NOTE]
88 | > Most of the endpoints are mocked but I want it to be as realistic as possible. An average user shouldnt tell the difference between the mock server and the original server. 😊 For more info see [TODO.md](TODO.md)
89 |
90 |
91 |
92 | ### Directory Structure
93 |
94 | ```
95 | src/
96 | ├── controllers/
97 | │ ├── Device/
98 | │ ├── Public/
99 | │ ├── Public/
100 | │ ├── User/
101 | │ └── ProductsStock/
102 | ├── routes/
103 | │ ├── Device/
104 | │ ├── Public/
105 | │ ├── User/
106 | │ └── ProductsStock/
107 | └── server/
108 | ├── app.ts
109 | └── index.ts
110 | ```
--------------------------------------------------------------------------------
/src/controllers/Device/device.types.ts:
--------------------------------------------------------------------------------
1 | export interface OpenDayRequest {
2 | fiscalDayNo: number;
3 | fiscalDayOpened: string;
4 | }
5 |
6 | export interface FiscalCounter {
7 | fiscalCounterType: "SaleByTax" | "SaleTaxByTax" | "CreditNoteByTax" | "CreditNoteTaxByTax" | "DebitNoteByTax" | "DebitNoteTaxByTax" | "BalanceByMoneyType" | "PayoutByTax" | "PayoutTaxByTax";
8 | fiscalCounterCurrency: string;
9 | fiscalCounterTaxPercent?: number;
10 | fiscalCounterTaxID?: number;
11 | fiscalCounterMoneyType?: "Cash" | "CreditCard" | "DebitCard" | "Check" | "WireTransfer" | "MobileMoney" | "Voucher" | "Other";
12 | fiscalCounterValue: number;
13 | }
14 |
15 | export interface CloseDayRequest {
16 | fiscalDayNo: number;
17 | fiscalDayCounters: FiscalCounter[];
18 | fiscalDayDeviceSignature: {
19 | "hash": string,
20 | "signature": string
21 | };
22 | receiptCounter: number;
23 | }
24 |
25 | export interface IssueCertificateRequest {
26 | certificateRequest: string
27 | }
28 |
29 | export interface PingResponse {
30 | reportingFrequency: number;
31 | operationID: string;
32 | }
33 |
34 | export interface SubmittedFileHeaderDtoListResponse {
35 | files: Array<{
36 | fileName: string;
37 | uploadedAt: string;
38 | status: string;
39 | }>;
40 | }
41 |
42 | export interface SubmitReceiptRequest {
43 | receiptType: "FiscalInvoice" | "FiscalInvoiceProforma" | "FiscalReceipt" | "NonFiscalReceipt" | "CreditNote" | "DebitNote" | "CreditNoteProforma" | "DebitNoteProforma";
44 | receiptCurrency: string;
45 | receiptCounter: number;
46 | receiptGlobalNo: number;
47 | invoiceNo: string;
48 | buyerData?: {
49 | buyerRegisterName: string;
50 | buyerTradeName: string;
51 | vatNumber?: string;
52 | buyerTIN?: string;
53 | buyerContacts?: {
54 | phoneNo?: string;
55 | email?: string;
56 | };
57 | buyerAddress?: {
58 | province?: string;
59 | city?: string;
60 | street?: string;
61 | houseNo?: string;
62 | district?: string;
63 | };
64 | };
65 | receiptNotes?: string;
66 | receiptDate: string;
67 | creditDebitNote?: {
68 | receiptID?: number;
69 | deviceID?: number;
70 | receiptGlobalNo?: number;
71 | fiscalDayNo?: number;
72 | };
73 | receiptLinesTaxInclusive: boolean;
74 | receiptLines: Array<{
75 | receiptLineType: "Sale" | "Discount";
76 | receiptLineNo: number;
77 | receiptLineHSCode?: string;
78 | receiptLineName: string;
79 | receiptLinePrice?: number;
80 | receiptLineQuantity: number;
81 | receiptLineTotal: number;
82 | taxCode?: string;
83 | taxPercent?: number;
84 | taxID: number;
85 | }>;
86 | receiptTaxes: Array<{
87 | taxCode?: string;
88 | taxPercent?: number;
89 | taxID: number;
90 | taxAmount: number;
91 | salesAmountWithTax: number;
92 | }>;
93 | receiptPayments: Array<{
94 | moneyTypeCode: "Cash" | "CreditCard" | "DebitCard" | "Check" | "WireTransfer" | "MobileMoney" | "Voucher" | "Other";
95 | paymentAmount: number;
96 | }>;
97 | receiptTotal: number;
98 | receiptPrintForm?: "Receipt48" | "InvoiceA4";
99 | receiptDeviceSignature: {
100 | hash: string;
101 | signature: string;
102 | };
103 | }
104 |
105 | export interface Receipt {
106 | receiptType: string;
107 | receiptCurrency: string;
108 | receiptCounter: number;
109 | receiptGlobalNo: number;
110 | invoiceNo: string;
111 | receiptDate: string;
112 | receiptLinesTaxInclusive: boolean;
113 | receiptLines: Array<{
114 | receiptLineType: string;
115 | receiptLineNo: number;
116 | receiptLineHSCode: string;
117 | receiptLineName: string;
118 | receiptLinePrice: number;
119 | receiptLineQuantity: number;
120 | receiptLineTotal: number;
121 | taxCode: string;
122 | taxPercent: number;
123 | taxID: number;
124 | }>;
125 | receiptTaxes: Array<{
126 | taxCode: string;
127 | taxPercent: number;
128 | taxID: number;
129 | taxAmount: number;
130 | salesAmountWithTax: number;
131 | }>;
132 | receiptPayments: Array<{
133 | moneyTypeCode: string;
134 | paymentAmount: number;
135 | }>;
136 | receiptTotal: number;
137 | receiptPrintForm: string;
138 | receiptDeviceSignature: {
139 | hash: string;
140 | signature: string;
141 | };
142 | }
143 |
144 | export interface RequestBody {
145 | header: {
146 | deviceId: number;
147 | fiscalDayNo: number;
148 | fiscalDayOpened: string;
149 | fileSequence: number;
150 | };
151 | content: {
152 | receipts: Receipt[];
153 | };
154 | footer: {
155 | fiscalDayCounters: Array;
156 | fiscalDayDeviceSignature: {
157 | hash: string;
158 | signature: string;
159 | };
160 | receiptCounter: number;
161 | fiscalDayClosed: string;
162 | };
163 | }
164 |
--------------------------------------------------------------------------------
/src/controllers/Public/index.ts:
--------------------------------------------------------------------------------
1 | import { Request, Response } from 'express';
2 | import generateOperationID from '../../utils/generateOperationID';
3 |
4 | // Add your public controller methods here
5 | // Example:
6 | // export const getPublicInfo = async (req: Request, res: Response) => {
7 | // try {
8 | // // Implementation
9 | // } catch (error) {
10 | // res.status(500).json({ error: 'Internal server error' });
11 | // }
12 | // };
13 |
14 | export const registerDevice = async (req: Request, res: Response) => {
15 | const { deviceID } = req.params;
16 | const DeviceModelName = req.header('DeviceModelName');
17 | const DeviceModelVersion = req.header('DeviceModelVersion');
18 | const requestBody = req.body;
19 |
20 | if (!deviceID || isNaN(Number(deviceID))) {
21 | return res.status(400).json({
22 | errorCode: "BAD_REQUEST",
23 | type: "https://httpstatuses.io/400",
24 | title: "Bad Request",
25 | status: 400,
26 | detail: "Invalid or missing device ID",
27 | operationID: generateOperationID(),
28 | });
29 | }
30 |
31 | if (!DeviceModelName || !DeviceModelVersion) {
32 | return res.status(400).json({
33 | errorCode: "BAD_REQUEST",
34 | type: "https://httpstatuses.io/400",
35 | title: "Bad Request",
36 | status: 400,
37 | detail: "Missing required headers",
38 | operationID: generateOperationID(),
39 | });
40 | }
41 |
42 | if (!requestBody || !requestBody.activationKey || !requestBody.certificateRequest || requestBody.certificateRequest == "invalid"
43 | || requestBody.activationKey === "invalid") {
44 | return res.status(422).json({
45 | errorCode: "DEV01",
46 | type: "https://httpstatuses.io/422",
47 | title: "Unprocessable Entity",
48 | status: 422,
49 | detail: "Device not found or not active",
50 | operationID: generateOperationID(),
51 | });
52 | }
53 |
54 | try {
55 | const response = {
56 | operationID: generateOperationID(),
57 | certificate: "-----BEGIN CERTIFICATE-----\nMIIC6TCCAdGgAwIBAgIFAKsSzWowDQYJKoZIhvcNAQELBQAwZDELMAkGA1UEBhMC\nTFQxETAPBgNVBAoMCEdvb2QgTHRkMScwJQYDVQQLDB5Hb29kIEx0ZCBDZXJ0aWZp\nY2F0ZSBBdXRob3JpdHkxGTAXBgNVBAMMEEdvb2QgTHRkIFJvb3QgQ0EwHhcNMTkx\nMDAzMTU1NzA1WhcNMjAxMDEyMTU1NzA1WjBfMQswCQYDVQQGEwJUWjERMA8GA1UE\nCAwIWmFuemliYXIxHzAdBgNVBAoMFlphbnppYmFyIFJldmVudWUgQm9hcmQxHDAa\nBgNVBAMME1pSQi1lVkZELTAwMDAwMDAwNDIwWTATBgcqhkjOPQIBBggqhkjOPQMB\nBwNCAAT7v3DvY7pRg4lz2Z87wSMwSX27KwlpYnSRV6WUiPjpq2XsUAbg2lhUN7q3\nmlNJaUzqoKPmop5qURIpqUydXfapo3IwcDAJBgNVHRMEAjAAMB8GA1UdIwQYMBaA\nFK1RXHm1plvaintqlWaXDs1X3LX+MB0GA1UdDgQWBBRqr96XrCUbuwCQawxO0//n\nTOCoNTAOBgNVHQ8BAf8EBAMCBeAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZI\nhvcNAQELBQADggEBANr1Wk1cVZB96yobFgK3rQQv9oXW+Jle7Jh36J2o4wSSB+RH\nlfMojDrqKVQCLrFDcF+8JIA3RTRKdduIXgBAr13xQ8JkHd1/o23yN6a2DaYgh0wr\nDrndlR6y1yG0vQuurJ3IgXmC0ldM5+VhalgmoCKFV9JsUD+GhOyJ6NWlc0SqvJCs\n3RZLYwZ4MNViPbRy0Kbp0ufY1zTbh02Gw9aVfFzUwL8GS00iMb4MnSav1xur7wQh\nBoF3PpNvu003P7f1eVJ62qVD2LWWntfn0mL1aRmDe2wpMQKAKhxto+sDb2mfJ6G6\nPFtwMHe7BUfiwTzGYqav21h1w/amPkxNVQ7Li4M=\n-----END CERTIFICATE-----",
58 | };
59 | res.status(200).json(response);
60 | } catch (error) {
61 | res.status(500).json({
62 | type: "https://httpstatuses.io/500",
63 | title: "Server error",
64 | status: 500,
65 | operationID: generateOperationID(),
66 | });
67 | }
68 | }
69 |
70 | export const getServerCertificate = async (req: Request, res: Response) => {
71 |
72 | const { thumbprint } = req.query;
73 | const operationId = "0HMPHA0KCMPHN:00000005";
74 |
75 | if (thumbprint && typeof thumbprint !== "string") {
76 | return res.status(400).json({
77 | type: "https://httpstatuses.io/400",
78 | title: "Bad Request",
79 | status: 400,
80 | operationID: operationId,
81 | detail: "Invalid thumbprint format."
82 | });
83 | }
84 |
85 | if (thumbprint === "notfound") {
86 | return res.status(404).json({
87 | type: "https://httpstatuses.io/404",
88 | title: "Not Found",
89 | status: 404,
90 | operationID: operationId
91 | });
92 | }
93 |
94 | if (thumbprint === "invalid") {
95 | return res.status(422).json({
96 | errorCode: "DEV01",
97 | type: "https://httpstatuses.io/422",
98 | title: "Unprocessable Entity",
99 | status: 422,
100 | detail: "Device not found or not active",
101 | operationID: operationId
102 | });
103 | }
104 |
105 | if (thumbprint === "error") {
106 | return res.status(500).json({
107 | type: "https://httpstatuses.io/500",
108 | title: "Server error",
109 | status: 500,
110 | operationID: operationId
111 | });
112 | }
113 |
114 | return res.status(200).json({
115 | operationID: operationId,
116 | certificate: [
117 | "-----BEGIN CERTIFICATE-----\nMIIDQTCCAikCFFLwDNnN3ZnAriN4wanJF439cX53MA0GCSqGSIb3DQEBCwUAMF0x\nCzAJBgNVBAYTAkxUMRMwEQYDVQQIDApFTEVLVFJFTkFJMRMwEQYDVQQHDApFTEVL\nVFJFTkFJMREwDwYDVQQKDAhldHJvbmlrYTERMA8GA1UEAwwIemltcmFfQ0EwHhcN\nMjMwMzE2MTA1NDAxWhcNMzMwMzEzMTA1NDAxWjBdMQswCQYDVQQGEwJMVDETMBEG\nA1UECAwKRUxFS1RSRU5BSTETMBEGA1UEBwwKRUxFS1RSRU5BSTERMA8GA1UECgwI\nZXRyb25pa2ExETAPBgNVBAMMCHppbXJhX0NBMIIBIjANBgkqhkiG9w0BAQEFAAOC\nAQ8AMIIBCgKCAQEA30dU24HCzSd+y4/ho41at23gh1g2Yjhk8SnUNo5PLn2uoUvj\nUemQNuJFjg14LvBPoubcIfOZW6cp9TCGy8KqG3WyVrT9z9sEl4fQMlEsCegmCEIE\nng7PvtsdJL9CaC7x11KK4az5UpzqUQ2gyYOryF6M8BT6wH5U61og2SWfv4M5ttQc\nbBDFbReeCYBLvSzFisI1CAVnc3CLqLhBN5jHxfraeZyAvLzBFnbYj7RBcv28iGRz\ny6LXtgE9yDeRdtCk8UqrgyMe//LWmlu+mmLb2IdIeD66GkD637FURa9lAcDJksUP\nUep2TyXq44JjMeNz7CyPbJ0wlV49cUlKc+/ZVQIDAQABMA0GCSqGSIb3DQEBCwUA\nA4IBAQAPVhhMAvjpQRm9OqZz3k97/yygqxeNKdTjxc/zVO8gj0pRBclVhxCnfj+P\nA1wc1nBEHvZ0oh03JviGQ8wxTLWUc0vWlZICmST7heC3DeA+xh90mLZOb2kK3cko\nY7kTAQ8cLV+ddI4UI46WQ6q/bhueOZQjMf1K2IP0fUhXxgFtrPXXrlkiUNX4tisg\ncy986/JjIHk2sY3OyBqYeFwq5J6DO2kMfLgHzwlaVWnTiXJ/etK17fynETImldZU\n9qSHYEyURqKuDyjELRThDLDTGwnsL5HU31+RCmGCZuNpjqkdne8hedNISdyCsMvD\ndDY0A7Vf+2WmfxWzg0wbhf6cIjxS\n-----END CERTIFICATE-----",
118 | "-----BEGIN CERTIFICATE-----\nMIIDcDCCAligAwIBAgIISVJfo63v2tswDQYJKoZIhvcNAQELBQAwXTELMAkGA1UE\nBhMCTFQxEzARBgNVBAgMCkVMRUtUUkVOQUkxEzARBgNVBAcMCkVMRUtUUkVOQUkx\nETAPBgNVBAoMCGV0cm9uaWthMREwDwYDVQQDDAh6aW1yYV9DQTAeFw0yMzAzMjAx\nOTM5NTVaFw0yNjAzMjAyMTIzMTBaMGwxCzAJBgNVBAYTAlpXMREwDwYDVQQIDAha\naW1iYWJ3ZTEsMCoGA1UECgwjWmltYmFid2UgRmlzY2FsaXNhdGlvbiBPcmdhbml6\nYXRpb24xHDAaBgNVBAMME1pSQi1lVkZELTAwMDAwMDAwNDIwWTATBgcqhkjOPQIB\nBggqhkjOPQMBBwNCAAT7v3DvY7pRg4lz2Z87wSMwSX27KwlpYnSRV6WUiPjpq2Xs\nUAbg2lhUN7q3mlNJaUzqoKPmop5qURIpqUydXfapo4HvMIHsMAkGA1UdEwQCMAAw\nHQYDVR0OBBYEFGqv3pesJRu7AJBrDE7T/+dM4Kg1MIGaBgNVHSMEgZIwgY+AFIKH\n58WkIDv0AUhEr+O0qvs6Dk7VoWGkXzBdMQswCQYDVQQGEwJMVDETMBEGA1UECAwK\nRUxFS1RSRU5BSTETMBEGA1UEBwwKRUxFS1RSRU5BSTERMA8GA1UECgwIZXRyb25p\na2ExETAPBgNVBAMMCHppbXJhX0NBghRS8AzZzd2ZwK4jeMGpyReN/XF+dzAOBgNV\nHQ8BAf8EBAMCBeAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQAD\nggEBAMkQykLAfhUGYaMR71kdwgFShstjK12v0sg69ruNtnlIajs3H9vaYoZRvPOV\n5jkdKlzF4Erp8D9URTJQD9aNCHqOZg1wSytuQqxedoThaWSYL3eiUf3Rig+II/fG\n/F+sr0pC6QrriJKRHH8aeAUF2jXD/CyI/GcftBIMTr91egV5Bn3Pjwfh8aEFzq7R\nqF4p0p8UBPwJtFUSqC4JkwLkpfG8bMpNHYic97+PRRLlrqiSPrQF/rlLQDC4IpMc\n9oMHuYHi2CmMcpnXLNZhgeFhHpILKOloU/AGtsExDS4gHCm/LfkUAz3p0KTIxnfx\nj5QjByFH8P3rY05BmSdE4aFUnxM=\n-----END CERTIFICATE-----"
119 | ],
120 | certificateValidTill: "2026-03-20T21:23:10"
121 | });
122 | }
123 |
124 | export const verifyTaxpayerInformation = async (req: Request, res: Response) => {
125 |
126 | const { deviceID } = req.params;
127 | const requestBody = req.body;
128 | const operationID = "0HMPDRRQL1C0G:00000005";
129 |
130 | if (!deviceID || isNaN(Number(deviceID))) {
131 | return res.status(400).json({
132 | type: "https://httpstatuses.io/400",
133 | title: "Bad Request",
134 | status: 400,
135 | operationID
136 | });
137 | }
138 |
139 | if (!requestBody || !requestBody.activationKey || !requestBody.deviceSerialNo || requestBody.deviceSerialNo == "invalid"
140 | || requestBody.activationKey === "invalid") {
141 | return res.status(422).json({
142 | errorCode: "DEV01",
143 | type: "https://httpstatuses.io/422",
144 | title: "Unprocessable Entity",
145 | status: 422,
146 | detail: "Device not found or not active",
147 | operationID
148 | });
149 | }
150 |
151 | // Simulating success response
152 | return res.status(200).json({
153 | operationID,
154 | taxpayerVerified: true,
155 | message: "Taxpayer information verified successfully"
156 | });
157 | }
158 |
159 |
--------------------------------------------------------------------------------
/src/controllers/User/index.ts:
--------------------------------------------------------------------------------
1 | import { Request, Response } from 'express';
2 | import generateOperationID from '../../utils/generateOperationID';
3 |
4 | export const getUsersList = (req: Request, res: Response) => {
5 | const { deviceID } = req.params;
6 | const { Sort, Order, Offset, Limit, Operator } = req.query;
7 | const DeviceModelName = req.header("DeviceModelName");
8 | const DeviceModelVersion = req.header("DeviceModelVersion");
9 |
10 | if (!deviceID || !Offset || !Limit) {
11 | return res.status(400).json({ message: "Missing required parameters" });
12 | }
13 |
14 | res.status(200).json({
15 | operationID: generateOperationID(),
16 | total: 10,
17 | rows: [
18 | {
19 | userName: "mockUser",
20 | personName: "John",
21 | personSurname: "Doe",
22 | userRole: "Admin",
23 | email: "john.doe@example.com",
24 | phoneNo: "+123456789",
25 | userStatus: "Active",
26 | },
27 | ],
28 | });
29 | };
30 |
31 | export const sendSecurityCodeToTaxpayer = (req: Request, res: Response) => {
32 | const { deviceID } = req.params;
33 | const DeviceModelName = req.header("DeviceModelName");
34 | const DeviceModelVersion = req.header("DeviceModelVersion");
35 | const { userName } = req.body;
36 |
37 | if (!deviceID || !userName) {
38 | return res.status(400).json({ message: "Missing required parameters" });
39 | }
40 |
41 | res.status(200).json({
42 | operationID: generateOperationID()
43 | });
44 | };
45 |
46 | export const createUser = (req: Request, res: Response) => {
47 | const { deviceID } = req.params;
48 | const DeviceModelName = req.header("DeviceModelName");
49 | const DeviceModelVersion = req.header("DeviceModelVersion");
50 | const { userName, personName, personSurname, userRole } = req.body;
51 |
52 | if (!deviceID || !userName || !personName || !personSurname || !userRole) {
53 | return res.status(400).json({
54 | "type": "https://httpstatuses.io/400",
55 | "title": "Bad Request",
56 | "status": 400,
57 | "detail": "Missing required parameters"
58 | });
59 | }
60 |
61 | res.status(200).json({
62 | operationID: generateOperationID(),
63 | message: "User created successfully.",
64 | });
65 | };
66 |
67 | export const loginUser = (req: Request, res: Response) => {
68 | const { deviceID } = req.params;
69 | const DeviceModelName = req.header("DeviceModelName");
70 | const DeviceModelVersion = req.header("DeviceModelVersion");
71 | const { userName, password } = req.body;
72 |
73 | if (!deviceID || !userName || !password) {
74 | return res.status(400).json({
75 | "type": "https://httpstatuses.io/400",
76 | "title": "Bad Request",
77 | "status": 400,
78 | "detail": "Missing required parameters"
79 | });
80 | }
81 |
82 | res.status(200).json({
83 | operationID: generateOperationID(),
84 | token: "mock-jwt-token",
85 | user: {
86 | userName,
87 | personName: "John",
88 | personSurname: "Doe",
89 | userRole: "Admin",
90 | email: "john.doe@example.com",
91 | phoneNo: "+123456789",
92 | },
93 | });
94 | };
95 |
96 | export const sendSecurityCodeToUserEmail = (req: Request, res: Response) => {
97 | const { deviceID } = req.params;
98 | const Token = req.header("Token");
99 | const DeviceModelName = req.header("DeviceModelName");
100 | const DeviceModelVersion = req.header("DeviceModelVersion");
101 | const { userEmail } = req.body;
102 |
103 | if (!deviceID || !Token || !userEmail) {
104 | return res.status(400).json({
105 | "type": "https://httpstatuses.io/400",
106 | "title": "Bad Request",
107 | "status": 400,
108 | "detail": "Missing required parameters"
109 | });
110 | }
111 |
112 | res.status(200).json({
113 | operationID: generateOperationID()
114 | });
115 | };
116 |
117 |
118 | export const sendSecurityCodeToUserPhone = (req: Request, res: Response) => {
119 | const { deviceID } = req.params;
120 | const Token = req.header("Token");
121 | const DeviceModelName = req.header("DeviceModelName");
122 | const DeviceModelVersion = req.header("DeviceModelVersion");
123 | const { phoneNo } = req.body;
124 |
125 | if (!deviceID || !Token || !phoneNo) {
126 | return res.status(400).json({
127 | "type": "https://httpstatuses.io/400",
128 | "title": "Bad Request",
129 | "status": 400,
130 | "detail": "Missing required parameters"
131 | });
132 | }
133 |
134 | res.status(200).json({
135 | operationID: generateOperationID()
136 | });
137 | };
138 |
139 |
140 | export const confirmUser = (req: Request, res: Response) => {
141 | const { deviceID } = req.params;
142 | const DeviceModelName = req.header("DeviceModelName");
143 | const DeviceModelVersion = req.header("DeviceModelVersion");
144 | const { userName, password, securityCode } = req.body;
145 |
146 | if (!deviceID || !userName || !password || !securityCode) {
147 | return res.status(400).json({
148 | "type": "https://httpstatuses.io/400",
149 | "title": "Bad Request",
150 | "status": 400,
151 | "detail": "Missing required parameters"
152 | });
153 | }
154 |
155 | // Check if userName is wrong
156 | if (userName === "invalid" || password === "invalid" || securityCode === "invalid") {
157 | return res.status(400).json({
158 | type: "https://httpstatuses.io/400",
159 | title: "Bad Request",
160 | status: 400,
161 | detail: "Invalid details"
162 | });
163 | }
164 |
165 |
166 | res.status(200).json({
167 | operationID: generateOperationID(),
168 | "user": {
169 | "userName": "johndoe123",
170 | "personName": "John",
171 | "personSurname": "Doe",
172 | "userRole": "User",
173 | "email": "john.doe@example.com",
174 | "phoneNo": "+1234567890"
175 | },
176 | "token": "string"
177 | });
178 | };
179 |
180 | export const changePassword = (req: Request, res: Response) => {
181 | const { deviceID } = req.params;
182 | const Token = req.header("Token");
183 | const DeviceModelName = req.header("DeviceModelName");
184 | const DeviceModelVersion = req.header("DeviceModelVersion");
185 | const { oldPassword, newPassword } = req.body;
186 |
187 | if (!deviceID || !Token || !oldPassword || !newPassword) {
188 | return res.status(400).json({
189 | "type": "https://httpstatuses.io/400",
190 | "title": "Bad Request",
191 | "status": 400,
192 | "detail": "Missing required parameters"
193 | });
194 | }
195 |
196 | // Check if oldPassword is wrong
197 | if (oldPassword === "invalid") {
198 | return res.status(400).json({
199 | type: "https://httpstatuses.io/400",
200 | title: "Bad Request",
201 | status: 400,
202 | detail: "Invalid old password"
203 | });
204 | }
205 |
206 | res.status(200).json({
207 | operationID: generateOperationID(),
208 | "user": {
209 | "userName": "johndoe123",
210 | "personName": "John",
211 | "personSurname": "Doe",
212 | "userRole": "User",
213 | "email": "john.doe@example.com",
214 | "phoneNo": "+1234567890"
215 | },
216 | "token": "string"
217 | });
218 | };
219 |
220 |
221 |
222 | export const resetPassword = (req: Request, res: Response) => {
223 | const { deviceID } = req.params;
224 | const DeviceModelName = req.header("DeviceModelName");
225 | const DeviceModelVersion = req.header("DeviceModelVersion");
226 | const { userName, channel } = req.body;
227 |
228 | if (!deviceID || !userName || !channel) {
229 | return res.status(400).json({
230 | "type": "https://httpstatuses.io/400",
231 | "title": "Bad Request",
232 | "status": 400,
233 | "detail": "Missing required parameters"
234 | });
235 | }
236 |
237 | // Check if oldPassword is wrong
238 | if (userName === "invalid" || channel === "invalid") {
239 | return res.status(400).json({
240 | type: "https://httpstatuses.io/400",
241 | title: "Bad Request",
242 | status: 400,
243 | detail: "Invalid user name or channel"
244 | });
245 | }
246 |
247 | res.status(200).json({
248 | operationID: generateOperationID()
249 | });
250 | };
251 |
252 |
253 | export const confirmContact = (req: Request, res: Response) => {
254 | const { deviceID } = req.params;
255 |
256 | const Token = req.header("Token");
257 |
258 | const DeviceModelName = req.header("DeviceModelName");
259 | const DeviceModelVersion = req.header("DeviceModelVersion");
260 | const { securityCode,channel } = req.body;
261 |
262 | if (!deviceID || !securityCode || !channel) {
263 | return res.status(400).json({
264 | "type": "https://httpstatuses.io/400",
265 | "title": "Bad Request",
266 | "status": 400,
267 | "detail": "Missing required parameters"
268 | });
269 | }
270 |
271 | // Check if userName is wrong
272 | if (securityCode === "invalid" || channel === "invalid") {
273 | return res.status(400).json({
274 | type: "https://httpstatuses.io/400",
275 | title: "Bad Request",
276 | status: 400,
277 | detail: "Invalid details"
278 | });
279 | }
280 |
281 |
282 | res.status(200).json({
283 | operationID: generateOperationID(),
284 | "user": {
285 | "userName": "johndoe123",
286 | "personName": "John",
287 | "personSurname": "Doe",
288 | "userRole": "User",
289 | "email": "john.doe@example.com",
290 | "phoneNo": "+1234567890"
291 | }
292 | });
293 | };
294 |
295 |
296 |
297 | export const update = (req: Request, res: Response) => {
298 | const { deviceID } = req.params;
299 | const Token = req.header("Token");
300 | const DeviceModelName = req.header("DeviceModelName");
301 | const DeviceModelVersion = req.header("DeviceModelVersion");
302 | const { userName, personName, personSurname, userRole, userStatus } = req.body;
303 |
304 | if (!deviceID || !userName || !personName || !personSurname || !userRole || !userStatus) {
305 | return res.status(400).json({
306 | "type": "https://httpstatuses.io/400",
307 | "title": "Bad Request",
308 | "status": 400,
309 | "detail": "Missing required parameters"
310 | });
311 | }
312 |
313 | // Check if userName is wrong
314 | if (userName === "invalid") {
315 | return res.status(400).json({
316 | type: "https://httpstatuses.io/400",
317 | title: "Bad Request",
318 | status: 400,
319 | detail: "Invalid details"
320 | });
321 | }
322 |
323 |
324 | res.status(200).json({
325 | operationID: generateOperationID()
326 | });
327 | };
328 |
329 | export const confirmPasswordReset = (req: Request, res: Response) => {
330 | const { deviceID } = req.params;
331 |
332 | const DeviceModelName = req.header("DeviceModelName");
333 | const DeviceModelVersion = req.header("DeviceModelVersion");
334 | const { userName, securityCode, newPassword } = req.body;
335 |
336 | if (!deviceID || !securityCode || !newPassword || !userName) {
337 | return res.status(400).json({
338 | "type": "https://httpstatuses.io/400",
339 | "title": "Bad Request",
340 | "status": 400,
341 | "detail": "Missing required parameters"
342 | });
343 | }
344 |
345 | // Check if userName is wrong
346 | if (securityCode === "invalid" || newPassword === "invalid") {
347 | return res.status(400).json({
348 | type: "https://httpstatuses.io/400",
349 | title: "Bad Request",
350 | status: 400,
351 | detail: "Invalid details"
352 | });
353 | }
354 |
355 |
356 | res.status(200).json({
357 | operationID: generateOperationID(),
358 | "user": {
359 | "userName": "johndoe123",
360 | "personName": "John",
361 | "personSurname": "Doe",
362 | "userRole": "User",
363 | "email": "john.doe@example.com",
364 | "phoneNo": "+1234567890"
365 | },
366 | "token": "string"
367 | });
368 | };
--------------------------------------------------------------------------------
/src/controllers/Device/index.ts:
--------------------------------------------------------------------------------
1 | import { Request, Response } from 'express';
2 |
3 | import generateOperationID from '../../utils/generateOperationID';
4 |
5 |
6 | import {
7 | CloseDayRequest,
8 | IssueCertificateRequest,
9 | OpenDayRequest,
10 | PingResponse,
11 | SubmitReceiptRequest,
12 | SubmittedFileHeaderDtoListResponse
13 | } from './device.types';
14 |
15 |
16 |
17 | export const getConfig = async (req: Request, res: Response) => {
18 |
19 | const { deviceID } = req.params;
20 | const deviceModelName = req.header('DeviceModelName');
21 | const deviceModelVersion = req.header('DeviceModelVersion');
22 |
23 | if (!deviceID || isNaN(Number(deviceID))) {
24 | return res.status(400).json({
25 | operationID: generateOperationID(),
26 | type: "https://httpstatuses.io/400",
27 | title: "Bad Request",
28 | status: 400,
29 | detail: "Invalid or missing deviceID",
30 | });
31 | }
32 |
33 | if (!deviceModelName || !deviceModelVersion) {
34 | return res.status(422).json({
35 | operationID: generateOperationID(),
36 | type: "https://httpstatuses.io/422",
37 | title: "Unprocessable Entity",
38 | status: 422,
39 | detail: "Missing required headers",
40 | });
41 | }
42 |
43 | // Mock expired certificate response
44 | if (deviceID === "999") {
45 | return res.status(401).json({
46 | operationID: generateOperationID(),
47 | type: "https://httpstatuses.io/401",
48 | title: "Unauthorized",
49 | status: 401,
50 | detail: "Device certificate expired.",
51 | });
52 | }
53 |
54 | // Mock server error response
55 | if (deviceID === "500") {
56 | return res.status(500).json({
57 | operationID: generateOperationID(),
58 | type: "https://httpstatuses.io/500",
59 | title: "Server error",
60 | status: 500
61 | });
62 | }
63 |
64 | // Mock successful response
65 | return res.status(200).json({
66 | operationID: generateOperationID(),
67 | taxPayerName: "Nienow, Hara and Schinner",
68 | taxPayerTIN: "3796605707",
69 | vatNumber: "3899488439",
70 | deviceSerialNo: `SN-${deviceID}`,
71 | deviceBranchName: "Shoes",
72 | deviceBranchAddress: {
73 | province: "Harare",
74 | street: "Torey Lakes",
75 | houseNo: "566",
76 | city: "Harare",
77 | },
78 | deviceBranchContacts: {
79 | phoneNo: "(320) 238-4248",
80 | email: "Leland_Gutmann@yahoo.com",
81 | },
82 | deviceOperatingMode: "Online",
83 | taxPayerDayMaxHrs: 24,
84 | applicableTaxes: [
85 | { taxPercent: 15, taxName: "15%" },
86 | { taxPercent: 0, taxName: "0%" },
87 | { taxName: "exempt" },
88 | ],
89 | certificateValidTill: "2026-03-30T17:15:40",
90 | qrUrl: "www.qrUrl.com",
91 | taxpayerDayEndNotificationHrs: 20
92 | });
93 |
94 | };
95 |
96 | export const getStatus = async (req: Request, res: Response) => {
97 | const { deviceID } = req.params;
98 | const deviceModelName = req.header('DeviceModelName');
99 | const deviceModelVersion = req.header('DeviceModelVersion');
100 |
101 | if (!deviceID || isNaN(Number(deviceID))) {
102 | return res.status(400).json({
103 | operationID: generateOperationID(),
104 | type: "https://httpstatuses.io/400",
105 | title: "Bad Request",
106 | status: 400,
107 | detail: "Invalid or missing deviceID",
108 | });
109 | }
110 |
111 | if (!deviceModelName || !deviceModelVersion) {
112 | return res.status(422).json({
113 | operationID: generateOperationID(),
114 | type: "https://httpstatuses.io/422",
115 | title: "Unprocessable Entity",
116 | status: 422,
117 | detail: "Missing required headers",
118 | });
119 | }
120 |
121 | // Mock expired certificate response
122 | if (deviceID === "999") {
123 | return res.status(401).json({
124 | operationID: generateOperationID(),
125 | type: "https://httpstatuses.io/401",
126 | title: "Unauthorized",
127 | status: 401,
128 | detail: "Device certificate expired.",
129 | });
130 | }
131 |
132 | // Mock server error response
133 | if (deviceID === "500") {
134 | return res.status(500).json({
135 | operationID: generateOperationID(),
136 | type: "https://httpstatuses.io/500",
137 | title: "Server error",
138 | status: 500
139 | });
140 | }
141 |
142 | // Mock successful response
143 | return res.status(200).json({
144 | operationID: generateOperationID(),
145 | fiscalDayStatus: "FiscalDayClosed",
146 | fiscalDayReconciliationMode: "Auto",
147 | fiscalDayServerSignature: {
148 | certificateThumbprint: "b785a0b4d8a734a55ba595d143b4cf72834cd88d",
149 | hash: "//To59fLHvuoRe2slUpN2grJu5adaodOW6kW1OYvf/c=",
150 | signature: "YyXTSizBBrMjMk4VQL+sCNr+2AC6aQbDAn9JMV2rk3yJ6MDZwie0wqQW3oisNWrMkeZsuAyFSnFkU2A+pKm91sOHVdjeRBebjQgAQQIMTCVIcYrx+BizQ7Ib9iCdsVI+Jel2nThqQiQzfRef6EgtgsaIAN+PV55xSrHvPkIe+Bc="
151 | },
152 | fiscalDayClosed: "2023-03-30T20:15:40",
153 | lastFiscalDayNo: 101,
154 | lastReceiptGlobalNo: 9931,
155 | });
156 | }
157 |
158 |
159 | export const openDay = async (req: Request, res: Response) => {
160 | const { deviceID } = req.params;
161 | const deviceModelName = req.header('DeviceModelName');
162 | const deviceModelVersion = req.header('DeviceModelVersion');
163 | const requestBody: OpenDayRequest = req.body;
164 |
165 | // Check if deviceID is provided and is valid
166 | if (!deviceID || isNaN(Number(deviceID))) {
167 | return res.status(400).json({
168 | operationID: generateOperationID(),
169 | type: "https://httpstatuses.io/400",
170 | title: "Bad Request",
171 | status: 400,
172 | detail: "Invalid or missing deviceID",
173 | });
174 | }
175 |
176 | // Validate that the required headers are provided
177 | if (!deviceModelName || !deviceModelVersion) {
178 | return res.status(422).json({
179 | operationID: generateOperationID(),
180 | type: "https://httpstatuses.io/422",
181 | title: "Unprocessable Entity",
182 | status: 422,
183 | detail: "Missing required headers",
184 | });
185 | }
186 |
187 | // Simulate expired certificate scenario
188 | if (deviceID === "999") {
189 | return res.status(401).json({
190 | operationID: generateOperationID(),
191 | type: "https://httpstatuses.io/401",
192 | title: "Unauthorized",
193 | status: 401,
194 | detail: "Device certificate expired.",
195 | });
196 | }
197 |
198 | // Simulate server error scenario
199 | if (deviceID === "500") {
200 | return res.status(500).json({
201 | operationID: generateOperationID(),
202 | type: "https://httpstatuses.io/500",
203 | title: "Server error",
204 | status: 500,
205 | });
206 | }
207 |
208 | // Simulate success response
209 | return res.status(200).json({
210 | operationID: generateOperationID(),
211 | fiscalDayNo: 102,
212 | });
213 | }
214 |
215 | export const closeDay = async (req: Request, res: Response) => {
216 |
217 | const { deviceID } = req.params;
218 | const deviceModelName = req.header('DeviceModelName');
219 | const deviceModelVersion = req.header('DeviceModelVersion');
220 | const requestBody: CloseDayRequest = req.body;
221 |
222 | // Validate deviceID
223 | if (!deviceID || isNaN(Number(deviceID))) {
224 | return res.status(400).json({
225 | operationID: generateOperationID(),
226 | type: "https://httpstatuses.io/400",
227 | title: "Bad Request",
228 | status: 400,
229 | detail: "Invalid or missing deviceID",
230 | });
231 | }
232 |
233 | // Validate required headers
234 | if (!deviceModelName || !deviceModelVersion) {
235 | return res.status(422).json({
236 | operationID: generateOperationID(),
237 | type: "https://httpstatuses.io/422",
238 | title: "Unprocessable Entity",
239 | status: 422,
240 | detail: "Missing required headers: DeviceModelName or DeviceModelVersion",
241 | });
242 | }
243 |
244 | // Simulate expired certificate scenario
245 | if (deviceID === "999") {
246 | return res.status(401).json({
247 | operationID: generateOperationID(),
248 | type: "https://httpstatuses.io/401",
249 | title: "Unauthorized",
250 | status: 401,
251 | detail: "Device certificate expired.",
252 | });
253 | }
254 |
255 | // Simulate server error scenario
256 | if (deviceID === "500") {
257 | return res.status(500).json({
258 | operationID: generateOperationID(),
259 | type: "https://httpstatuses.io/500",
260 | title: "Server error",
261 | status: 500
262 | });
263 | }
264 |
265 | // Simulate successful Close Day response
266 | return res.status(200).json({
267 | operationID: generateOperationID(),
268 | });
269 |
270 | }
271 |
272 |
273 |
274 | export const issueCertificate = async (req: Request, res: Response) => {
275 | const { deviceID } = req.params;
276 | const deviceModelName = req.header('DeviceModelName');
277 | const deviceModelVersion = req.header('DeviceModelVersion');
278 | const requestBody: IssueCertificateRequest = req.body;
279 |
280 | // Validate deviceID
281 | if (!deviceID || isNaN(Number(deviceID))) {
282 | return res.status(400).json({
283 | operationID: generateOperationID(),
284 | type: "https://httpstatuses.io/400",
285 | title: "Bad Request",
286 | status: 400,
287 | detail: "Invalid or missing deviceID",
288 | });
289 | }
290 |
291 | // Validate required headers
292 | if (!deviceModelName || !deviceModelVersion) {
293 | return res.status(422).json({
294 | operationID: generateOperationID(),
295 | type: "https://httpstatuses.io/422",
296 | title: "Unprocessable Entity",
297 | status: 422,
298 | detail: "Missing required headers: DeviceModelName or DeviceModelVersion",
299 | });
300 | }
301 |
302 | // Simulate expired certificate scenario
303 | if (deviceID === "999") {
304 | return res.status(401).json({
305 | operationID: generateOperationID(),
306 | type: "https://httpstatuses.io/401",
307 | title: "Unauthorized",
308 | status: 401,
309 | detail: "Device certificate expired.",
310 | });
311 | }
312 |
313 | // Simulate server error scenario
314 | if (deviceID === "500") {
315 | return res.status(500).json({
316 | operationID: generateOperationID(),
317 | type: "https://httpstatuses.io/500",
318 | title: "Server error",
319 | status: 500,
320 | });
321 | }
322 |
323 | // Simulate successful certificate issuance
324 | return res.status(200).json({
325 | operationID: generateOperationID(),
326 | certificate: `-----BEGIN CERTIFICATE-----
327 | MIIC6TCCAdGgAwIBAgIFAKsSzWowDQYJKoZIhvcNAQELBQAwZDELMAkGA1UEBhMC
328 | TFQxETAPBgNVBAoMCEdvb2QgTHRkMScwJQYDVQQLDB5Hb29kIEx0ZCBDZXJ0aWZp
329 | Y2F0ZSBBdXRob3JpdHkxGTAXBgNVBAMMEEdvb2QgTHRkIFJvb3QgQ0EwHhcNMTkx
330 | MDAzMTU1NzA1WhcNMjAxMDEyMTU1NzA1WjBfMQswCQYDVQQGEwJUWjERMA8GA1UE
331 | CAwIWmFuemliYXIxHzAdBgNVBAoMFlphbnppYmFyIFJldmVudWUgQm9hcmQxHDAa
332 | BgNVBAMME1pSQi1lVkZELTAwMDAwMDAwNDIwWTATBgcqhkjOPQIBBggqhkjOPQMB
333 | BwNCAAT7v3DvY7pRg4lz2Z87wSMwSX27KwlpYnSRV6WUiPjpq2XsUAbg2lhUN7q3
334 | mlNJaUzqoKPmop5qURIpqUydXfapo3IwcDAJBgNVHRMEAjAAMB8GA1UdIwQYMBaA
335 | FK1RXHm1plvaintqlWaXDs1X3LX+MB0GA1UdDgQWBBRqr96XrCUbuwCQawxO0//n
336 | TOCoNTAOBgNVHQ8BAf8EBAMCBeAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZI
337 | hvcNAQELBQADggEBANr1Wk1cVZB96yobFgK3rQQv9oXW+Jle7Jh36J2o4wSSB+RH
338 | lfMojDrqKVQCLrFDcF+8JIA3RTRKdduIXgBAr13xQ8JkHd1/o23yN6a2DaYgh0wr
339 | DrndlR6y1yG0vQuurJ3IgXmC0ldM5+VhalgmoCKFV9JsUD+GhOyJ6NWlc0SqvJCs
340 | 3RZLYwZ4MNViPbRy0Kbp0ufY1zTbh02Gw9aVfFzUwL8GS00iMb4MnSav1xur7wQh
341 | BoF3PpNvu003P7f1eVJ62qVD2LWWntfn0mL1aRmDe2wpMQKAKhxto+sDb2mfJ6G6
342 | PFtwMHe7BUfiwTzGYqav21h1w/amPkxNVQ7Li4M=
343 | -----END CERTIFICATE-----`
344 | });
345 |
346 | }
347 |
348 |
349 | export const submitReciept = async (req: Request, res: Response) => {
350 |
351 | const { deviceID } = req.params; // deviceID from path
352 | const deviceModelName = req.header('DeviceModelName');
353 | const deviceModelVersion = req.header('DeviceModelVersion');
354 | const requestBody: SubmitReceiptRequest = req.body; // Body of the request
355 |
356 | // Handle mock responses based on some conditions
357 | if (!deviceModelName || !deviceModelVersion) {
358 | return res.status(400).json({
359 | type: 'https://httpstatuses.io/400',
360 | title: 'Bad Request',
361 | status: 400,
362 | operationID: generateOperationID(),
363 | });
364 | }
365 |
366 | if (deviceID === '12345') {
367 | return res.status(401).json({
368 | type: 'https://httpstatuses.io/401',
369 | title: 'Device certificate expired.',
370 | status: 401,
371 | operationID: generateOperationID(),
372 | });
373 | }
374 |
375 | // Simulate server error for some condition
376 | if (deviceID === '99999') {
377 | return res.status(500).json({
378 | type: 'https://httpstatuses.io/500',
379 | title: 'Server error',
380 | status: 500,
381 | operationID: generateOperationID(),
382 | });
383 | }
384 |
385 | // On success, return the mock response
386 | return res.status(200).json({
387 | receiptID: 600,
388 | serverDate: '2023-05-04T16:45:37',
389 | receiptServerSignature: {
390 | certificateThumbprint: 'F9B295CA65BA22B94F6D4B27E48D08BF6CD7F7C8',
391 | hash: '8IURjBbdTy2b6EnUzSEHHCjIenorq5TdYSCtuzCVisw=',
392 | signature: 'gz/JZQVw5Mk7vCTVx02hrZEQS1vAnMIEnwVdl/eouL9SkYbmZFrfQLVtfhPwxM2SCzgrqf9dpuQi1/t9u7T1t5Vvl/vkMW8FLH0u2IReOXLakxFx9TNWu7XH20FqjCJLXOB3NYAiVshAHtYpwPmU9gYCJBTwfhKAjmJaYpIkUvXE+cXKsV4Zxuvm7y25jOGs2RlLExmVw2uT53aRLoLbHdIxaelq8Pgx+YEJQNz9/AniRyjQRdOD5FyQgu00IU9SydrcpkM6xA01fHsNnB53ATb6CdGBAXv88I42n6o8E784CI8wCGWTF6lEoN6sMnLQPqyxY9YQj0ZxcvW5xhC9uA==',
393 | },
394 | operationID: generateOperationID(),
395 | });
396 | }
397 |
398 |
399 | export const ping = async (req: Request, res: Response) => {
400 | // Extract path parameter (deviceID) and headers (DeviceModelName and DeviceModelVersion)
401 | const { deviceID } = req.params; // deviceID from path
402 | const deviceModelName = req.header('DeviceModelName');
403 | const deviceModelVersion = req.header('DeviceModelVersion');
404 |
405 | // Check if the required parameters are missing
406 | if (!deviceModelName || !deviceModelVersion) {
407 | return res.status(400).json({
408 | type: 'https://httpstatuses.io/400',
409 | title: 'Bad Request',
410 | status: 400,
411 | operationID: '00000000',
412 | });
413 | }
414 |
415 | // Simulate device certificate expiration
416 | if (deviceID === '12345') {
417 | return res.status(401).json({
418 | type: 'https://httpstatuses.io/401',
419 | title: 'Device certificate expired.',
420 | status: 401,
421 | operationID: '0HMPDRRQL1C0G:00000005',
422 | });
423 | }
424 |
425 | // Simulate server error for specific deviceID
426 | if (deviceID === '99999') {
427 | return res.status(500).json({
428 | type: 'https://httpstatuses.io/500',
429 | title: 'Server error',
430 | status: 500,
431 | operationID: '0HMPDRRQL1C0G:00000005',
432 | });
433 | }
434 |
435 | // Simulate success response with a mock PingResponse
436 | // Return the success response with a 200 status code
437 | return res.status(200).json({
438 | reportingFrequency: 5,
439 | operationID: '0HMS2LV2BED20:00000001',
440 | });
441 |
442 | }
443 |
444 | export const submitFile = async (req: Request, res: Response) => {
445 |
446 | const { deviceID } = req.params;
447 | const DeviceModelName = req.header('DeviceModelName');
448 | const DeviceModelVersion = req.header('DeviceModelVersion');
449 | const requestBody = req.body;
450 |
451 | if (!requestBody.content) {
452 | return res.status(400).json({
453 | operationId: generateOperationID(),
454 | type: 'https://httpstatuses.io/400',
455 | title: 'Bad request',
456 | status: 400,
457 | detail: 'Content is empty',
458 | });
459 | }
460 |
461 |
462 |
463 | if (!deviceID || !DeviceModelName || !DeviceModelVersion || !requestBody) {
464 | return res.status(400).json({
465 | type: 'https://httpstatuses.io/400',
466 | title: 'Bad request',
467 | status: 400,
468 | detail: 'Required parameters are missing',
469 | });
470 | }
471 |
472 | if (deviceID !== '1111') {
473 | return res.status(404).json({
474 | type: 'https://httpstatuses.io/404',
475 | title: 'Not Found',
476 | status: 404,
477 | detail: "Not existing device with provided device id",
478 | });
479 | }
480 |
481 | if (requestBody.footer.fiscalDayCounters[0].fiscalCounterType !== 'saleByTax') {
482 | return res.status(422).json({
483 | type: 'https://httpstatuses.io/422',
484 | title: 'Unprocessable Entity',
485 | status: 422,
486 | detail: 'Device fiscal day status must be FiscalDayClosed',
487 | });
488 | }
489 |
490 | return res.status(200).json({
491 | operationID: generateOperationID(),
492 |
493 | });
494 | }
495 |
496 | export const submittedFileList = async (req: Request, res: Response) => {
497 |
498 | const {
499 | OperationID,
500 | FileUploadedFrom,
501 | FileUploadedTill,
502 | Sort,
503 | Order,
504 | Offset,
505 | Limit,
506 | Operator,
507 | } = req.query;
508 |
509 | const { deviceID } = req.params;
510 | const { DeviceModelName, DeviceModelVersion } = req.headers;
511 |
512 | console.log('Received parameters:', req.query);
513 |
514 | // Mock response data
515 | const responseData: SubmittedFileHeaderDtoListResponse = {
516 | files: [
517 | {
518 | fileName: 'file1.txt',
519 | uploadedAt: '2023-02-11T10:00:00Z',
520 | status: 'processed',
521 | },
522 | {
523 | fileName: 'file2.txt',
524 | uploadedAt: '2023-02-10T09:30:00Z',
525 | status: 'pending',
526 | },
527 | ],
528 | };
529 |
530 | // Mock response codes based on parameters or logic
531 | if (deviceID === 'invalid') {
532 | return res.status(404).json({
533 | operationId: generateOperationID(),
534 | type: 'https://httpstatuses.io/404',
535 | title: 'Not Found',
536 | status: 404,
537 | detail: 'Not existing device with provided device id',
538 | });
539 | }
540 |
541 | if (!OperationID) {
542 | return res.status(400).json({
543 | operationId: generateOperationID(),
544 | type: 'https://httpstatuses.io/400',
545 | title: 'Bad request',
546 | status: 400,
547 | detail: 'Operation ID is missing',
548 | });
549 | }
550 |
551 | return res.status(200).json({
552 | operationId: generateOperationID(),
553 | files: responseData.files,
554 | });
555 | }
--------------------------------------------------------------------------------
/swagger/Public-1.json:
--------------------------------------------------------------------------------
1 | {
2 | "openapi": "3.0.1",
3 | "info": {
4 | "title": "Fiscal backend FiscalDeviceApi Build:1.0.0.0",
5 | "version": "1.0"
6 | },
7 | "paths": {
8 | "/Public/v1/{deviceID}/RegisterDevice": {
9 | "post": {
10 | "tags": [
11 | "Public"
12 | ],
13 | "description": "Endpoint is used to get device certificate and register device in Fiscalisation Backend (link device with Fiscalisation Backend).",
14 | "parameters": [
15 | {
16 | "name": "deviceID",
17 | "in": "path",
18 | "description": "Sold or active device ID",
19 | "required": true,
20 | "schema": {
21 | "type": "integer",
22 | "format": "int32"
23 | }
24 | },
25 | {
26 | "name": "DeviceModelName",
27 | "in": "header",
28 | "description": "Device model name as registered in Tax Authority",
29 | "required": true,
30 | "schema": {
31 | "type": "string"
32 | }
33 | },
34 | {
35 | "name": "DeviceModelVersion",
36 | "in": "header",
37 | "description": "Device model version number as registered in Tax Authority",
38 | "required": true,
39 | "schema": {
40 | "type": "string"
41 | }
42 | }
43 | ],
44 | "requestBody": {
45 | "description": "",
46 | "content": {
47 | "application/json": {
48 | "schema": {
49 | "allOf": [
50 | {
51 | "$ref": "#/components/schemas/RegisterDeviceRequest"
52 | }
53 | ]
54 | }
55 | }
56 | },
57 | "required": true
58 | },
59 | "responses": {
60 | "400": {
61 | "description": "Bad Request",
62 | "headers": {
63 | "operationId": {
64 | "description": "unique operation id",
65 | "schema": {
66 | "type": "string",
67 | "description": "unique operation id",
68 | "format": ""
69 | }
70 | }
71 | },
72 | "content": {
73 | "application/problem+json": {
74 | "schema": {
75 | "$ref": "#/components/schemas/ValidationProblemDetails"
76 | }
77 | }
78 | }
79 | },
80 | "422": {
81 | "description": "Operation failed because of provided data or invalid object state in Fiscal backend. Returns problem details structure as described in https://www.rfc-editor.org/rfc/rfc7807 with errorCode field to specify error.",
82 | "headers": {
83 | "operationId": {
84 | "description": "unique operation id",
85 | "schema": {
86 | "type": "string",
87 | "description": "unique operation id",
88 | "format": ""
89 | }
90 | }
91 | },
92 | "content": {
93 | "application/problem+json": {
94 | "schema": {
95 | "$ref": "#/components/schemas/ApiProblemDetails"
96 | },
97 | "example": {
98 | "errorCode": "DEV01",
99 | "type": "https://httpstatuses.io/422",
100 | "title": "Unprocessable Entity",
101 | "status": 422,
102 | "detail": "Device not found or not active",
103 | "operationID": "0HMPDRRQL1C0G:00000005"
104 | }
105 | }
106 | }
107 | },
108 | "500": {
109 | "description": "Server encountered temporary issues.",
110 | "headers": {
111 | "operationId": {
112 | "description": "unique operation id",
113 | "schema": {
114 | "type": "string",
115 | "description": "unique operation id",
116 | "format": ""
117 | }
118 | }
119 | },
120 | "content": {
121 | "application/problem+json": {
122 | "schema": {
123 | "$ref": "#/components/schemas/ProblemDetails"
124 | },
125 | "example": {
126 | "type": "https://httpstatuses.io/500",
127 | "title": "Server error",
128 | "status": 500,
129 | "operationID": "0HMPDRRQL1C0G:00000005"
130 | }
131 | }
132 | }
133 | },
134 | "200": {
135 | "description": "Success",
136 | "headers": {
137 | "operationId": {
138 | "description": "unique operation id",
139 | "schema": {
140 | "type": "string",
141 | "description": "unique operation id",
142 | "format": ""
143 | }
144 | }
145 | },
146 | "content": {
147 | "application/json": {
148 | "schema": {
149 | "$ref": "#/components/schemas/RegisterDeviceResponse"
150 | },
151 | "example": {
152 | "operationID": "0HMPH9AF0QKKE:00000005",
153 | "certificate": "-----BEGIN CERTIFICATE-----\nMIIC6TCCAdGgAwIBAgIFAKsSzWowDQYJKoZIhvcNAQELBQAwZDELMAkGA1UEBhMC\nTFQxETAPBgNVBAoMCEdvb2QgTHRkMScwJQYDVQQLDB5Hb29kIEx0ZCBDZXJ0aWZp\nY2F0ZSBBdXRob3JpdHkxGTAXBgNVBAMMEEdvb2QgTHRkIFJvb3QgQ0EwHhcNMTkx\nMDAzMTU1NzA1WhcNMjAxMDEyMTU1NzA1WjBfMQswCQYDVQQGEwJUWjERMA8GA1UE\nCAwIWmFuemliYXIxHzAdBgNVBAoMFlphbnppYmFyIFJldmVudWUgQm9hcmQxHDAa\nBgNVBAMME1pSQi1lVkZELTAwMDAwMDAwNDIwWTATBgcqhkjOPQIBBggqhkjOPQMB\nBwNCAAT7v3DvY7pRg4lz2Z87wSMwSX27KwlpYnSRV6WUiPjpq2XsUAbg2lhUN7q3\nmlNJaUzqoKPmop5qURIpqUydXfapo3IwcDAJBgNVHRMEAjAAMB8GA1UdIwQYMBaA\nFK1RXHm1plvaintqlWaXDs1X3LX+MB0GA1UdDgQWBBRqr96XrCUbuwCQawxO0//n\nTOCoNTAOBgNVHQ8BAf8EBAMCBeAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZI\nhvcNAQELBQADggEBANr1Wk1cVZB96yobFgK3rQQv9oXW+Jle7Jh36J2o4wSSB+RH\nlfMojDrqKVQCLrFDcF+8JIA3RTRKdduIXgBAr13xQ8JkHd1/o23yN6a2DaYgh0wr\nDrndlR6y1yG0vQuurJ3IgXmC0ldM5+VhalgmoCKFV9JsUD+GhOyJ6NWlc0SqvJCs\n3RZLYwZ4MNViPbRy0Kbp0ufY1zTbh02Gw9aVfFzUwL8GS00iMb4MnSav1xur7wQh\nBoF3PpNvu003P7f1eVJ62qVD2LWWntfn0mL1aRmDe2wpMQKAKhxto+sDb2mfJ6G6\nPFtwMHe7BUfiwTzGYqav21h1w/amPkxNVQ7Li4M=\n-----END CERTIFICATE-----"
154 | }
155 | }
156 | }
157 | }
158 | }
159 | }
160 | },
161 | "/Public/v1/GetServerCertificate": {
162 | "get": {
163 | "tags": [
164 | "Public"
165 | ],
166 | "description": "Endpoint is used to retrieve Fiscalisation Backend certificate for Fiscalisation Backend signature validation. Despite of the parameter is provided or not, and despite what certificate in the chain thumbprint indicates (first, second or third level certificate), full certificate chain is returned",
167 | "parameters": [
168 | {
169 | "name": "thumbprint",
170 | "in": "query",
171 | "description": "Thumbprint of Fiscalisation Backend certificate which should be returned. If field is not provided, currently active Fiscalisation Backend signing certificate is returned",
172 | "schema": {
173 | "maxLength": 40,
174 | "minLength": 0,
175 | "type": "string"
176 | },
177 | "example": "b785a0b4d8a734a55ba595d143b4cf72834cd88d"
178 | }
179 | ],
180 | "responses": {
181 | "400": {
182 | "description": "Bad Request",
183 | "headers": {
184 | "operationId": {
185 | "description": "unique operation id",
186 | "schema": {
187 | "type": "string",
188 | "description": "unique operation id",
189 | "format": ""
190 | }
191 | }
192 | },
193 | "content": {
194 | "application/problem+json": {
195 | "schema": {
196 | "$ref": "#/components/schemas/ValidationProblemDetails"
197 | }
198 | }
199 | }
200 | },
201 | "422": {
202 | "description": "Operation failed because of provided data or invalid object state in Fiscal backend. Returns problem details structure as described in https://www.rfc-editor.org/rfc/rfc7807 with errorCode field to specify error.",
203 | "headers": {
204 | "operationId": {
205 | "description": "unique operation id",
206 | "schema": {
207 | "type": "string",
208 | "description": "unique operation id",
209 | "format": ""
210 | }
211 | }
212 | },
213 | "content": {
214 | "application/problem+json": {
215 | "schema": {
216 | "$ref": "#/components/schemas/ApiProblemDetails"
217 | },
218 | "example": {
219 | "errorCode": "DEV01",
220 | "type": "https://httpstatuses.io/422",
221 | "title": "Unprocessable Entity",
222 | "status": 422,
223 | "detail": "Device not found or not active",
224 | "operationID": "0HMPDRRQL1C0G:00000005"
225 | }
226 | }
227 | }
228 | },
229 | "500": {
230 | "description": "Server encountered temporary issues.",
231 | "headers": {
232 | "operationId": {
233 | "description": "unique operation id",
234 | "schema": {
235 | "type": "string",
236 | "description": "unique operation id",
237 | "format": ""
238 | }
239 | }
240 | },
241 | "content": {
242 | "application/problem+json": {
243 | "schema": {
244 | "$ref": "#/components/schemas/ProblemDetails"
245 | },
246 | "example": {
247 | "type": "https://httpstatuses.io/500",
248 | "title": "Server error",
249 | "status": 500,
250 | "operationID": "0HMPDRRQL1C0G:00000005"
251 | }
252 | }
253 | }
254 | },
255 | "200": {
256 | "description": "Success",
257 | "headers": {
258 | "operationId": {
259 | "description": "unique operation id",
260 | "schema": {
261 | "type": "string",
262 | "description": "unique operation id",
263 | "format": ""
264 | }
265 | }
266 | },
267 | "content": {
268 | "application/json": {
269 | "schema": {
270 | "$ref": "#/components/schemas/GetServerCertificateResponse"
271 | },
272 | "example": {
273 | "operationID": "0HMPHA0KCMPHN:00000005",
274 | "certificate": [
275 | "-----BEGIN CERTIFICATE-----\nMIIDQTCCAikCFFLwDNnN3ZnAriN4wanJF439cX53MA0GCSqGSIb3DQEBCwUAMF0x\nCzAJBgNVBAYTAkxUMRMwEQYDVQQIDApFTEVLVFJFTkFJMRMwEQYDVQQHDApFTEVL\nVFJFTkFJMREwDwYDVQQKDAhldHJvbmlrYTERMA8GA1UEAwwIemltcmFfQ0EwHhcN\nMjMwMzE2MTA1NDAxWhcNMzMwMzEzMTA1NDAxWjBdMQswCQYDVQQGEwJMVDETMBEG\nA1UECAwKRUxFS1RSRU5BSTETMBEGA1UEBwwKRUxFS1RSRU5BSTERMA8GA1UECgwI\nZXRyb25pa2ExETAPBgNVBAMMCHppbXJhX0NBMIIBIjANBgkqhkiG9w0BAQEFAAOC\nAQ8AMIIBCgKCAQEA30dU24HCzSd+y4/ho41at23gh1g2Yjhk8SnUNo5PLn2uoUvj\nUemQNuJFjg14LvBPoubcIfOZW6cp9TCGy8KqG3WyVrT9z9sEl4fQMlEsCegmCEIE\nng7PvtsdJL9CaC7x11KK4az5UpzqUQ2gyYOryF6M8BT6wH5U61og2SWfv4M5ttQc\nbBDFbReeCYBLvSzFisI1CAVnc3CLqLhBN5jHxfraeZyAvLzBFnbYj7RBcv28iGRz\ny6LXtgE9yDeRdtCk8UqrgyMe//LWmlu+mmLb2IdIeD66GkD637FURa9lAcDJksUP\nUep2TyXq44JjMeNz7CyPbJ0wlV49cUlKc+/ZVQIDAQABMA0GCSqGSIb3DQEBCwUA\nA4IBAQAPVhhMAvjpQRm9OqZz3k97/yygqxeNKdTjxc/zVO8gj0pRBclVhxCnfj+P\nA1wc1nBEHvZ0oh03JviGQ8wxTLWUc0vWlZICmST7heC3DeA+xh90mLZOb2kK3cko\nY7kTAQ8cLV+ddI4UI46WQ6q/bhueOZQjMf1K2IP0fUhXxgFtrPXXrlkiUNX4tisg\ncy986/JjIHk2sY3OyBqYeFwq5J6DO2kMfLgHzwlaVWnTiXJ/etK17fynETImldZU\n9qSHYEyURqKuDyjELRThDLDTGwnsL5HU31+RCmGCZuNpjqkdne8hedNISdyCsMvD\ndDY0A7Vf+2WmfxWzg0wbhf6cIjxS\n-----END CERTIFICATE-----",
276 | "-----BEGIN CERTIFICATE-----\nMIIDcDCCAligAwIBAgIISVJfo63v2tswDQYJKoZIhvcNAQELBQAwXTELMAkGA1UE\nBhMCTFQxEzARBgNVBAgMCkVMRUtUUkVOQUkxEzARBgNVBAcMCkVMRUtUUkVOQUkx\nETAPBgNVBAoMCGV0cm9uaWthMREwDwYDVQQDDAh6aW1yYV9DQTAeFw0yMzAzMjAx\nOTM5NTVaFw0yNjAzMjAyMTIzMTBaMGwxCzAJBgNVBAYTAlpXMREwDwYDVQQIDAha\naW1iYWJ3ZTEsMCoGA1UECgwjWmltYmFid2UgRmlzY2FsaXNhdGlvbiBPcmdhbml6\nYXRpb24xHDAaBgNVBAMME1pSQi1lVkZELTAwMDAwMDAwNDIwWTATBgcqhkjOPQIB\nBggqhkjOPQMBBwNCAAT7v3DvY7pRg4lz2Z87wSMwSX27KwlpYnSRV6WUiPjpq2Xs\nUAbg2lhUN7q3mlNJaUzqoKPmop5qURIpqUydXfapo4HvMIHsMAkGA1UdEwQCMAAw\nHQYDVR0OBBYEFGqv3pesJRu7AJBrDE7T/+dM4Kg1MIGaBgNVHSMEgZIwgY+AFIKH\n58WkIDv0AUhEr+O0qvs6Dk7VoWGkXzBdMQswCQYDVQQGEwJMVDETMBEGA1UECAwK\nRUxFS1RSRU5BSTETMBEGA1UEBwwKRUxFS1RSRU5BSTERMA8GA1UECgwIZXRyb25p\na2ExETAPBgNVBAMMCHppbXJhX0NBghRS8AzZzd2ZwK4jeMGpyReN/XF+dzAOBgNV\nHQ8BAf8EBAMCBeAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQAD\nggEBAMkQykLAfhUGYaMR71kdwgFShstjK12v0sg69ruNtnlIajs3H9vaYoZRvPOV\n5jkdKlzF4Erp8D9URTJQD9aNCHqOZg1wSytuQqxedoThaWSYL3eiUf3Rig+II/fG\n/F+sr0pC6QrriJKRHH8aeAUF2jXD/CyI/GcftBIMTr91egV5Bn3Pjwfh8aEFzq7R\nqF4p0p8UBPwJtFUSqC4JkwLkpfG8bMpNHYic97+PRRLlrqiSPrQF/rlLQDC4IpMc\n9oMHuYHi2CmMcpnXLNZhgeFhHpILKOloU/AGtsExDS4gHCm/LfkUAz3p0KTIxnfx\nj5QjByFH8P3rY05BmSdE4aFUnxM=\n-----END CERTIFICATE-----"
277 | ],
278 | "certificateValidTill": "2026-03-20T21:23:10"
279 | }
280 | }
281 | }
282 | },
283 | "404": {
284 | "description": "Certificate requested by thumbprint not found",
285 | "headers": {
286 | "operationId": {
287 | "description": "unique operation id",
288 | "schema": {
289 | "type": "string",
290 | "description": "unique operation id",
291 | "format": ""
292 | }
293 | }
294 | },
295 | "content": {
296 | "application/problem+json": {
297 | "schema": {
298 | "$ref": "#/components/schemas/ProblemDetails"
299 | },
300 | "example": {
301 | "type": "https://httpstatuses.io/404",
302 | "title": "Not Found",
303 | "status": 400,
304 | "operationID": "0HMPDRRQL1C0G:00000005"
305 | }
306 | }
307 | }
308 | }
309 | }
310 | }
311 | },
312 | "/Public/v1/{deviceID}/VerifyTaxpayerInformation": {
313 | "post": {
314 | "tags": [
315 | "Public"
316 | ],
317 | "description": "Endpoint is used to retrieve taxpayer information from system before device registration (in order user could double check if device is going to be registered to correct taxpayer).",
318 | "parameters": [
319 | {
320 | "name": "deviceID",
321 | "in": "path",
322 | "description": "Sold or active device ID",
323 | "required": true,
324 | "schema": {
325 | "type": "integer",
326 | "format": "int32"
327 | }
328 | }
329 | ],
330 | "requestBody": {
331 | "description": "",
332 | "content": {
333 | "application/json": {
334 | "schema": {
335 | "allOf": [
336 | {
337 | "$ref": "#/components/schemas/VerifyTaxpayerInformationRequest"
338 | }
339 | ]
340 | }
341 | }
342 | },
343 | "required": true
344 | },
345 | "responses": {
346 | "400": {
347 | "description": "Bad Request",
348 | "headers": {
349 | "operationId": {
350 | "description": "unique operation id",
351 | "schema": {
352 | "type": "string",
353 | "description": "unique operation id",
354 | "format": ""
355 | }
356 | }
357 | },
358 | "content": {
359 | "application/problem+json": {
360 | "schema": {
361 | "$ref": "#/components/schemas/ValidationProblemDetails"
362 | }
363 | }
364 | }
365 | },
366 | "422": {
367 | "description": "Operation failed because of provided data or invalid object state in Fiscal backend. Returns problem details structure as described in https://www.rfc-editor.org/rfc/rfc7807 with errorCode field to specify error.",
368 | "headers": {
369 | "operationId": {
370 | "description": "unique operation id",
371 | "schema": {
372 | "type": "string",
373 | "description": "unique operation id",
374 | "format": ""
375 | }
376 | }
377 | },
378 | "content": {
379 | "application/problem+json": {
380 | "schema": {
381 | "$ref": "#/components/schemas/ApiProblemDetails"
382 | },
383 | "example": {
384 | "errorCode": "DEV01",
385 | "type": "https://httpstatuses.io/422",
386 | "title": "Unprocessable Entity",
387 | "status": 422,
388 | "detail": "Device not found or not active",
389 | "operationID": "0HMPDRRQL1C0G:00000005"
390 | }
391 | }
392 | }
393 | },
394 | "500": {
395 | "description": "Server encountered temporary issues.",
396 | "headers": {
397 | "operationId": {
398 | "description": "unique operation id",
399 | "schema": {
400 | "type": "string",
401 | "description": "unique operation id",
402 | "format": ""
403 | }
404 | }
405 | },
406 | "content": {
407 | "application/problem+json": {
408 | "schema": {
409 | "$ref": "#/components/schemas/ProblemDetails"
410 | },
411 | "example": {
412 | "type": "https://httpstatuses.io/500",
413 | "title": "Server error",
414 | "status": 500,
415 | "operationID": "0HMPDRRQL1C0G:00000005"
416 | }
417 | }
418 | }
419 | },
420 | "200": {
421 | "description": "Success",
422 | "headers": {
423 | "operationId": {
424 | "description": "unique operation id",
425 | "schema": {
426 | "type": "string",
427 | "description": "unique operation id",
428 | "format": ""
429 | }
430 | }
431 | },
432 | "content": {
433 | "application/json": {
434 | "schema": {
435 | "$ref": "#/components/schemas/VerifyTaxpayerInformationResponse"
436 | }
437 | }
438 | }
439 | }
440 | }
441 | }
442 | }
443 | },
444 | "components": {
445 | "schemas": {
446 | "AddressDto": {
447 | "required": [
448 | "city",
449 | "houseNo",
450 | "province",
451 | "street"
452 | ],
453 | "type": "object",
454 | "properties": {
455 | "province": {
456 | "maxLength": 100,
457 | "minLength": 0,
458 | "type": "string"
459 | },
460 | "city": {
461 | "maxLength": 100,
462 | "minLength": 0,
463 | "type": "string"
464 | },
465 | "street": {
466 | "maxLength": 100,
467 | "minLength": 0,
468 | "type": "string"
469 | },
470 | "houseNo": {
471 | "maxLength": 250,
472 | "minLength": 0,
473 | "type": "string"
474 | },
475 | "district": {
476 | "maxLength": 100,
477 | "minLength": 0,
478 | "type": "string",
479 | "nullable": true
480 | }
481 | },
482 | "additionalProperties": false
483 | },
484 | "ApiProblemDetails": {
485 | "type": "object",
486 | "properties": {
487 | "type": {
488 | "type": "string",
489 | "nullable": true
490 | },
491 | "title": {
492 | "type": "string",
493 | "nullable": true
494 | },
495 | "status": {
496 | "type": "integer",
497 | "format": "int32",
498 | "nullable": true
499 | },
500 | "detail": {
501 | "type": "string",
502 | "nullable": true
503 | },
504 | "instance": {
505 | "type": "string",
506 | "nullable": true
507 | },
508 | "errorCode": {
509 | "type": "string",
510 | "nullable": true
511 | }
512 | },
513 | "additionalProperties": { }
514 | },
515 | "Contacts": {
516 | "type": "object",
517 | "properties": {
518 | "phoneNo": {
519 | "maxLength": 20,
520 | "minLength": 0,
521 | "type": "string",
522 | "nullable": true
523 | },
524 | "email": {
525 | "maxLength": 100,
526 | "minLength": 0,
527 | "pattern": "\\A(?:[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?\\.)+[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?)\\Z",
528 | "type": "string",
529 | "nullable": true
530 | }
531 | },
532 | "additionalProperties": false
533 | },
534 | "GetServerCertificateResponse": {
535 | "required": [
536 | "operationID"
537 | ],
538 | "type": "object",
539 | "properties": {
540 | "operationID": {
541 | "maxLength": 60,
542 | "minLength": 0,
543 | "type": "string",
544 | "description": "Operation ID assigned by Fiscalisation Backend.",
545 | "example": "0HMPH9AF0QKKE:00000005"
546 | },
547 | "certificate": {
548 | "type": "array",
549 | "items": {
550 | "type": "string"
551 | },
552 | "description": "Fiscalisation Backend certificate chain (according x.509 standard) to validate Fiscalisation Backend signatures.",
553 | "nullable": true
554 | },
555 | "certificateValidTill": {
556 | "type": "string",
557 | "description": "Date till when Fiscalisation Backend signing certificate is valid (despite that in the certificate parameter all the certificate chain is returned, this field shows validity time of the child certificate in the chain). Times is provided in UTC time.",
558 | "format": "date-time"
559 | }
560 | },
561 | "additionalProperties": false
562 | },
563 | "ProblemDetails": {
564 | "type": "object",
565 | "properties": {
566 | "type": {
567 | "type": "string",
568 | "nullable": true
569 | },
570 | "title": {
571 | "type": "string",
572 | "nullable": true
573 | },
574 | "status": {
575 | "type": "integer",
576 | "format": "int32",
577 | "nullable": true
578 | },
579 | "detail": {
580 | "type": "string",
581 | "nullable": true
582 | },
583 | "instance": {
584 | "type": "string",
585 | "nullable": true
586 | }
587 | },
588 | "additionalProperties": { }
589 | },
590 | "RegisterDeviceRequest": {
591 | "required": [
592 | "activationKey",
593 | "certificateRequest"
594 | ],
595 | "type": "object",
596 | "properties": {
597 | "certificateRequest": {
598 | "minLength": 1,
599 | "type": "string",
600 | "description": "Certificate signing request (CSR) for which certificate will be generated (in PEM format).\r\nAssigned by Tax Authority device name (format: [CLIENT]-[Fiscal_device_serial_no]-[zero_padded_10_digit_deviceId]) should be provided in CSR`s Subject CN.\r\nSupported algorithms and key types (in order of suggested preference):\r\n1)\tECC ECDSA on SECG secp256r1 curve (also named as ANSI prime256v1, NIST P-256); Signature Algorithm: ecdsa-with-SHA256.\r\n2)\tRSA 2048; Signature Algorithm - SHA256WithRSA.",
601 | "example": "-----BEGIN CERTIFICATE REQUEST-----\\nMIHYMIGAAgEAMB4xHDAaBgNVBAMME1pSQi1lVkZELTAwMDAwMDAwNDIwWTATBgcq\\nhkjOPQIBBggqhkjOPQMBBwNCAAT7v3DvY7pRg4lz2Z87wSMwSX27KwlpYnSRV6WU\\niPjpq2XsUAbg2lhUN7q3mlNJaUzqoKPmop5qURIpqUydXfapoAAwCgYIKoZIzj0E\\nAwIDRwAwRAIgLMEJQDh18bUE9waT2UXzP0+8FcGukpcIegMxd1A4JaQCIAZkzmEH\\ne0aaZ2jIcZArZo+rWzI4IwnSXtJqXLrpGUML\\n-----END CERTIFICATE REQUEST-----"
602 | },
603 | "activationKey": {
604 | "maxLength": 8,
605 | "minLength": 0,
606 | "type": "string",
607 | "description": "Case insensitive 8 symbols key",
608 | "example": "12AXC178"
609 | }
610 | },
611 | "additionalProperties": false
612 | },
613 | "RegisterDeviceResponse": {
614 | "required": [
615 | "certificate",
616 | "operationID"
617 | ],
618 | "type": "object",
619 | "properties": {
620 | "operationID": {
621 | "maxLength": 60,
622 | "minLength": 0,
623 | "type": "string",
624 | "description": "Operation ID assigned by Fiscalisation Backend.",
625 | "example": "0HMPH9AF0QKKE:00000005"
626 | },
627 | "certificate": {
628 | "minLength": 1,
629 | "type": "string"
630 | }
631 | },
632 | "additionalProperties": false
633 | },
634 | "ValidationProblemDetails": {
635 | "type": "object",
636 | "properties": {
637 | "type": {
638 | "type": "string",
639 | "nullable": true
640 | },
641 | "title": {
642 | "type": "string",
643 | "nullable": true
644 | },
645 | "status": {
646 | "type": "integer",
647 | "format": "int32",
648 | "nullable": true
649 | },
650 | "detail": {
651 | "type": "string",
652 | "nullable": true
653 | },
654 | "instance": {
655 | "type": "string",
656 | "nullable": true
657 | },
658 | "errors": {
659 | "type": "object",
660 | "additionalProperties": {
661 | "type": "array",
662 | "items": {
663 | "type": "string"
664 | }
665 | },
666 | "nullable": true
667 | }
668 | },
669 | "additionalProperties": { }
670 | },
671 | "VerifyTaxpayerInformationRequest": {
672 | "required": [
673 | "activationKey",
674 | "deviceSerialNo"
675 | ],
676 | "type": "object",
677 | "properties": {
678 | "activationKey": {
679 | "maxLength": 8,
680 | "minLength": 1,
681 | "type": "string",
682 | "description": "Case insensitive 8 symbols key",
683 | "example": "12AXC178"
684 | },
685 | "deviceSerialNo": {
686 | "maxLength": 20,
687 | "minLength": 1,
688 | "type": "string",
689 | "description": "Device serial number assigned by manufacturer.",
690 | "example": "SN-001"
691 | }
692 | },
693 | "additionalProperties": false
694 | },
695 | "VerifyTaxpayerInformationResponse": {
696 | "required": [
697 | "deviceBranchAddress",
698 | "deviceBranchName",
699 | "operationID",
700 | "taxPayerName",
701 | "taxPayerTIN"
702 | ],
703 | "type": "object",
704 | "properties": {
705 | "operationID": {
706 | "maxLength": 60,
707 | "minLength": 0,
708 | "type": "string",
709 | "description": "Operation ID assigned by Fiscalisation Backend.",
710 | "example": "0HMPH9AF0QKKE:00000005"
711 | },
712 | "taxPayerName": {
713 | "maxLength": 250,
714 | "minLength": 1,
715 | "type": "string"
716 | },
717 | "taxPayerTIN": {
718 | "maxLength": 10,
719 | "minLength": 1,
720 | "type": "string"
721 | },
722 | "vatNumber": {
723 | "maxLength": 9,
724 | "type": "string",
725 | "nullable": true
726 | },
727 | "deviceBranchName": {
728 | "maxLength": 250,
729 | "minLength": 1,
730 | "type": "string"
731 | },
732 | "deviceBranchAddress": {
733 | "allOf": [
734 | {
735 | "$ref": "#/components/schemas/AddressDto"
736 | }
737 | ]
738 | },
739 | "deviceBranchContacts": {
740 | "allOf": [
741 | {
742 | "$ref": "#/components/schemas/Contacts"
743 | }
744 | ],
745 | "nullable": true
746 | }
747 | },
748 | "additionalProperties": false
749 | }
750 | }
751 | },
752 | "tags": [
753 | {
754 | "name": "Public",
755 | "description": "Public endpoints do not require client certificate to authenticate."
756 | }
757 | ]
758 | }
--------------------------------------------------------------------------------
/swagger/User-1.json:
--------------------------------------------------------------------------------
1 | {
2 | "openapi": "3.0.1",
3 | "info": {
4 | "title": "Fiscal backend FiscalDeviceApi Build:1.0.0.0",
5 | "version": "1.0"
6 | },
7 | "paths": {
8 | "/User/v1/{deviceID}/GetUsersList": {
9 | "get": {
10 | "tags": [
11 | "User"
12 | ],
13 | "description": "Endpoint is used to get taxpayer users saved in Fiscal device management sistem list.",
14 | "parameters": [
15 | {
16 | "name": "Sort",
17 | "in": "query",
18 | "schema": {
19 | "allOf": [
20 | {
21 | "$ref": "#/components/schemas/GetUsersListEnum"
22 | }
23 | ]
24 | }
25 | },
26 | {
27 | "name": "Order",
28 | "in": "query",
29 | "schema": {
30 | "allOf": [
31 | {
32 | "$ref": "#/components/schemas/ListRequestOrderEnum"
33 | }
34 | ]
35 | }
36 | },
37 | {
38 | "name": "Offset",
39 | "in": "query",
40 | "required": true,
41 | "schema": {
42 | "type": "integer",
43 | "format": "int32"
44 | }
45 | },
46 | {
47 | "name": "Limit",
48 | "in": "query",
49 | "required": true,
50 | "schema": {
51 | "type": "integer",
52 | "format": "int32"
53 | }
54 | },
55 | {
56 | "name": "Operator",
57 | "in": "query",
58 | "schema": {
59 | "allOf": [
60 | {
61 | "$ref": "#/components/schemas/LogicalOperator"
62 | }
63 | ]
64 | }
65 | },
66 | {
67 | "name": "deviceID",
68 | "in": "path",
69 | "required": true,
70 | "schema": {
71 | "type": "integer",
72 | "format": "int32"
73 | }
74 | },
75 | {
76 | "name": "DeviceModelName",
77 | "in": "header",
78 | "description": "Device model name as registered in Tax Authority",
79 | "schema": {
80 | "type": "string"
81 | }
82 | },
83 | {
84 | "name": "DeviceModelVersion",
85 | "in": "header",
86 | "description": "Device model version number as registered in Tax Authority",
87 | "schema": {
88 | "type": "string"
89 | }
90 | }
91 | ],
92 | "responses": {
93 | "401": {
94 | "description": "Device certificate expired.",
95 | "headers": {
96 | "operationId": {
97 | "description": "unique operation id",
98 | "schema": {
99 | "type": "string",
100 | "description": "unique operation id",
101 | "format": ""
102 | }
103 | }
104 | },
105 | "content": {
106 | "application/problem+json": {
107 | "schema": {
108 | "$ref": "#/components/schemas/ProblemDetails"
109 | }
110 | }
111 | }
112 | },
113 | "500": {
114 | "description": "Server encountered temporary issues.",
115 | "headers": {
116 | "operationId": {
117 | "description": "unique operation id",
118 | "schema": {
119 | "type": "string",
120 | "description": "unique operation id",
121 | "format": ""
122 | }
123 | }
124 | },
125 | "content": {
126 | "application/problem+json": {
127 | "schema": {
128 | "$ref": "#/components/schemas/ProblemDetails"
129 | },
130 | "example": {
131 | "type": "https://httpstatuses.io/500",
132 | "title": "Server error",
133 | "status": 500,
134 | "operationID": "0HMPDRRQL1C0G:00000005"
135 | }
136 | }
137 | }
138 | },
139 | "200": {
140 | "description": "Success",
141 | "headers": {
142 | "operationId": {
143 | "description": "unique operation id",
144 | "schema": {
145 | "type": "string",
146 | "description": "unique operation id",
147 | "format": ""
148 | }
149 | }
150 | },
151 | "content": {
152 | "application/json": {
153 | "schema": {
154 | "$ref": "#/components/schemas/GetUsersResponse"
155 | }
156 | }
157 | }
158 | },
159 | "400": {
160 | "description": "Bad Request",
161 | "headers": {
162 | "operationId": {
163 | "description": "unique operation id",
164 | "schema": {
165 | "type": "string",
166 | "description": "unique operation id",
167 | "format": ""
168 | }
169 | }
170 | },
171 | "content": {
172 | "application/problem+json": {
173 | "schema": {
174 | "$ref": "#/components/schemas/ValidationProblemDetails"
175 | }
176 | }
177 | }
178 | },
179 | "422": {
180 | "description": "Operation failed because of provided data or invalid object state in Fiscal backend. Returns problem details structure as described in https://www.rfc-editor.org/rfc/rfc7807 with errorCode field to specify error.",
181 | "headers": {
182 | "operationId": {
183 | "description": "unique operation id",
184 | "schema": {
185 | "type": "string",
186 | "description": "unique operation id",
187 | "format": ""
188 | }
189 | }
190 | },
191 | "content": {
192 | "application/problem+json": {
193 | "schema": {
194 | "$ref": "#/components/schemas/ApiProblemDetails"
195 | }
196 | }
197 | }
198 | }
199 | }
200 | }
201 | },
202 | "/User/v1/{deviceID}/SendSecurityCodeToTaxpayer": {
203 | "post": {
204 | "tags": [
205 | "User"
206 | ],
207 | "description": "Endpoint is responsible for security code sending to taxpayer and branch where device registered emails.",
208 | "parameters": [
209 | {
210 | "name": "deviceID",
211 | "in": "path",
212 | "required": true,
213 | "schema": {
214 | "type": "integer",
215 | "format": "int32"
216 | }
217 | },
218 | {
219 | "name": "DeviceModelName",
220 | "in": "header",
221 | "description": "Device model name as registered in Tax Authority",
222 | "schema": {
223 | "type": "string"
224 | }
225 | },
226 | {
227 | "name": "DeviceModelVersion",
228 | "in": "header",
229 | "description": "Device model version number as registered in Tax Authority",
230 | "schema": {
231 | "type": "string"
232 | }
233 | }
234 | ],
235 | "requestBody": {
236 | "description": "",
237 | "content": {
238 | "application/json": {
239 | "schema": {
240 | "allOf": [
241 | {
242 | "$ref": "#/components/schemas/SendSecurityCodeToTaxpayerRequest"
243 | }
244 | ]
245 | }
246 | }
247 | },
248 | "required": true
249 | },
250 | "responses": {
251 | "401": {
252 | "description": "Device certificate expired.",
253 | "headers": {
254 | "operationId": {
255 | "description": "unique operation id",
256 | "schema": {
257 | "type": "string",
258 | "description": "unique operation id",
259 | "format": ""
260 | }
261 | }
262 | },
263 | "content": {
264 | "application/problem+json": {
265 | "schema": {
266 | "$ref": "#/components/schemas/ProblemDetails"
267 | }
268 | }
269 | }
270 | },
271 | "500": {
272 | "description": "Server encountered temporary issues.",
273 | "headers": {
274 | "operationId": {
275 | "description": "unique operation id",
276 | "schema": {
277 | "type": "string",
278 | "description": "unique operation id",
279 | "format": ""
280 | }
281 | }
282 | },
283 | "content": {
284 | "application/problem+json": {
285 | "schema": {
286 | "$ref": "#/components/schemas/ProblemDetails"
287 | },
288 | "example": {
289 | "type": "https://httpstatuses.io/500",
290 | "title": "Server error",
291 | "status": 500,
292 | "operationID": "0HMPDRRQL1C0G:00000005"
293 | }
294 | }
295 | }
296 | },
297 | "200": {
298 | "description": "Success",
299 | "headers": {
300 | "operationId": {
301 | "description": "unique operation id",
302 | "schema": {
303 | "type": "string",
304 | "description": "unique operation id",
305 | "format": ""
306 | }
307 | }
308 | },
309 | "content": {
310 | "application/json": {
311 | "schema": {
312 | "$ref": "#/components/schemas/SendSecurityCodeToTaxpayerResponse"
313 | }
314 | }
315 | }
316 | },
317 | "404": {
318 | "description": "Not Found",
319 | "headers": {
320 | "operationId": {
321 | "description": "unique operation id",
322 | "schema": {
323 | "type": "string",
324 | "description": "unique operation id",
325 | "format": ""
326 | }
327 | }
328 | },
329 | "content": {
330 | "application/problem+json": {
331 | "schema": {
332 | "$ref": "#/components/schemas/ProblemDetails"
333 | }
334 | }
335 | }
336 | },
337 | "400": {
338 | "description": "Bad Request",
339 | "headers": {
340 | "operationId": {
341 | "description": "unique operation id",
342 | "schema": {
343 | "type": "string",
344 | "description": "unique operation id",
345 | "format": ""
346 | }
347 | }
348 | },
349 | "content": {
350 | "application/problem+json": {
351 | "schema": {
352 | "$ref": "#/components/schemas/ValidationProblemDetails"
353 | }
354 | }
355 | }
356 | },
357 | "422": {
358 | "description": "Operation failed because of provided data or invalid object state in Fiscal backend. Returns problem details structure as described in https://www.rfc-editor.org/rfc/rfc7807 with errorCode field to specify error.",
359 | "headers": {
360 | "operationId": {
361 | "description": "unique operation id",
362 | "schema": {
363 | "type": "string",
364 | "description": "unique operation id",
365 | "format": ""
366 | }
367 | }
368 | },
369 | "content": {
370 | "application/problem+json": {
371 | "schema": {
372 | "$ref": "#/components/schemas/ApiProblemDetails"
373 | }
374 | }
375 | }
376 | }
377 | }
378 | }
379 | },
380 | "/User/v1/{deviceID}/CreateUser": {
381 | "post": {
382 | "tags": [
383 | "User"
384 | ],
385 | "description": "Creates new pos user or updates allready existing not comfirmed tenant user",
386 | "parameters": [
387 | {
388 | "name": "deviceID",
389 | "in": "path",
390 | "required": true,
391 | "schema": {
392 | "type": "integer",
393 | "format": "int32"
394 | }
395 | },
396 | {
397 | "name": "DeviceModelName",
398 | "in": "header",
399 | "description": "Device model name as registered in Tax Authority",
400 | "schema": {
401 | "type": "string"
402 | }
403 | },
404 | {
405 | "name": "DeviceModelVersion",
406 | "in": "header",
407 | "description": "Device model version number as registered in Tax Authority",
408 | "schema": {
409 | "type": "string"
410 | }
411 | }
412 | ],
413 | "requestBody": {
414 | "content": {
415 | "application/json": {
416 | "schema": {
417 | "allOf": [
418 | {
419 | "$ref": "#/components/schemas/CreateUserRequest"
420 | }
421 | ]
422 | }
423 | }
424 | }
425 | },
426 | "responses": {
427 | "401": {
428 | "description": "Device certificate expired.",
429 | "headers": {
430 | "operationId": {
431 | "description": "unique operation id",
432 | "schema": {
433 | "type": "string",
434 | "description": "unique operation id",
435 | "format": ""
436 | }
437 | }
438 | },
439 | "content": {
440 | "application/problem+json": {
441 | "schema": {
442 | "$ref": "#/components/schemas/ProblemDetails"
443 | }
444 | }
445 | }
446 | },
447 | "500": {
448 | "description": "Server encountered temporary issues.",
449 | "headers": {
450 | "operationId": {
451 | "description": "unique operation id",
452 | "schema": {
453 | "type": "string",
454 | "description": "unique operation id",
455 | "format": ""
456 | }
457 | }
458 | },
459 | "content": {
460 | "application/problem+json": {
461 | "schema": {
462 | "$ref": "#/components/schemas/ProblemDetails"
463 | },
464 | "example": {
465 | "type": "https://httpstatuses.io/500",
466 | "title": "Server error",
467 | "status": 500,
468 | "operationID": "0HMPDRRQL1C0G:00000005"
469 | }
470 | }
471 | }
472 | },
473 | "200": {
474 | "description": "Success",
475 | "headers": {
476 | "operationId": {
477 | "description": "unique operation id",
478 | "schema": {
479 | "type": "string",
480 | "description": "unique operation id",
481 | "format": ""
482 | }
483 | }
484 | },
485 | "content": {
486 | "application/json": {
487 | "schema": {
488 | "$ref": "#/components/schemas/CreateUserResponse"
489 | }
490 | }
491 | }
492 | },
493 | "400": {
494 | "description": "Bad Request",
495 | "headers": {
496 | "operationId": {
497 | "description": "unique operation id",
498 | "schema": {
499 | "type": "string",
500 | "description": "unique operation id",
501 | "format": ""
502 | }
503 | }
504 | },
505 | "content": {
506 | "application/problem+json": {
507 | "schema": {
508 | "$ref": "#/components/schemas/ValidationProblemDetails"
509 | }
510 | }
511 | }
512 | },
513 | "422": {
514 | "description": "Operation failed because of provided data or invalid object state in Fiscal backend. Returns problem details structure as described in https://www.rfc-editor.org/rfc/rfc7807 with errorCode field to specify error.",
515 | "headers": {
516 | "operationId": {
517 | "description": "unique operation id",
518 | "schema": {
519 | "type": "string",
520 | "description": "unique operation id",
521 | "format": ""
522 | }
523 | }
524 | },
525 | "content": {
526 | "application/problem+json": {
527 | "schema": {
528 | "$ref": "#/components/schemas/ApiProblemDetails"
529 | }
530 | }
531 | }
532 | }
533 | }
534 | }
535 | },
536 | "/User/v1/{deviceID}/Login": {
537 | "post": {
538 | "tags": [
539 | "User"
540 | ],
541 | "description": "Endpoint is used to check if sent username and password credentials are correct and user can login to POS.",
542 | "parameters": [
543 | {
544 | "name": "deviceID",
545 | "in": "path",
546 | "required": true,
547 | "schema": {
548 | "type": "integer",
549 | "format": "int32"
550 | }
551 | },
552 | {
553 | "name": "DeviceModelName",
554 | "in": "header",
555 | "description": "Device model name as registered in Tax Authority",
556 | "schema": {
557 | "type": "string"
558 | }
559 | },
560 | {
561 | "name": "DeviceModelVersion",
562 | "in": "header",
563 | "description": "Device model version number as registered in Tax Authority",
564 | "schema": {
565 | "type": "string"
566 | }
567 | }
568 | ],
569 | "requestBody": {
570 | "description": "",
571 | "content": {
572 | "application/json": {
573 | "schema": {
574 | "allOf": [
575 | {
576 | "$ref": "#/components/schemas/LoginRequest"
577 | }
578 | ]
579 | }
580 | }
581 | }
582 | },
583 | "responses": {
584 | "401": {
585 | "description": "Device certificate expired.",
586 | "headers": {
587 | "operationId": {
588 | "description": "unique operation id",
589 | "schema": {
590 | "type": "string",
591 | "description": "unique operation id",
592 | "format": ""
593 | }
594 | }
595 | },
596 | "content": {
597 | "application/problem+json": {
598 | "schema": {
599 | "$ref": "#/components/schemas/ProblemDetails"
600 | }
601 | }
602 | }
603 | },
604 | "500": {
605 | "description": "Server encountered temporary issues.",
606 | "headers": {
607 | "operationId": {
608 | "description": "unique operation id",
609 | "schema": {
610 | "type": "string",
611 | "description": "unique operation id",
612 | "format": ""
613 | }
614 | }
615 | },
616 | "content": {
617 | "application/problem+json": {
618 | "schema": {
619 | "$ref": "#/components/schemas/ProblemDetails"
620 | },
621 | "example": {
622 | "type": "https://httpstatuses.io/500",
623 | "title": "Server error",
624 | "status": 500,
625 | "operationID": "0HMPDRRQL1C0G:00000005"
626 | }
627 | }
628 | }
629 | },
630 | "200": {
631 | "description": "Success",
632 | "headers": {
633 | "operationId": {
634 | "description": "unique operation id",
635 | "schema": {
636 | "type": "string",
637 | "description": "unique operation id",
638 | "format": ""
639 | }
640 | }
641 | },
642 | "content": {
643 | "application/json": {
644 | "schema": {
645 | "$ref": "#/components/schemas/LoginResponse"
646 | }
647 | }
648 | }
649 | },
650 | "400": {
651 | "description": "Bad Request",
652 | "headers": {
653 | "operationId": {
654 | "description": "unique operation id",
655 | "schema": {
656 | "type": "string",
657 | "description": "unique operation id",
658 | "format": ""
659 | }
660 | }
661 | },
662 | "content": {
663 | "application/problem+json": {
664 | "schema": {
665 | "$ref": "#/components/schemas/ValidationProblemDetails"
666 | }
667 | }
668 | }
669 | },
670 | "422": {
671 | "description": "Operation failed because of provided data or invalid object state in Fiscal backend. Returns problem details structure as described in https://www.rfc-editor.org/rfc/rfc7807 with errorCode field to specify error.",
672 | "headers": {
673 | "operationId": {
674 | "description": "unique operation id",
675 | "schema": {
676 | "type": "string",
677 | "description": "unique operation id",
678 | "format": ""
679 | }
680 | }
681 | },
682 | "content": {
683 | "application/problem+json": {
684 | "schema": {
685 | "$ref": "#/components/schemas/ApiProblemDetails"
686 | }
687 | }
688 | }
689 | }
690 | }
691 | }
692 | },
693 | "/User/v1/{deviceID}/SendSecurityCodeToUserEmail": {
694 | "post": {
695 | "tags": [
696 | "User"
697 | ],
698 | "description": "Sends security code to confirm user email",
699 | "parameters": [
700 | {
701 | "name": "Token",
702 | "in": "header",
703 | "required": true,
704 | "schema": {
705 | "type": "string"
706 | }
707 | },
708 | {
709 | "name": "deviceID",
710 | "in": "path",
711 | "required": true,
712 | "schema": {
713 | "type": "integer",
714 | "format": "int32"
715 | }
716 | },
717 | {
718 | "name": "DeviceModelName",
719 | "in": "header",
720 | "description": "Device model name as registered in Tax Authority",
721 | "schema": {
722 | "type": "string"
723 | }
724 | },
725 | {
726 | "name": "DeviceModelVersion",
727 | "in": "header",
728 | "description": "Device model version number as registered in Tax Authority",
729 | "schema": {
730 | "type": "string"
731 | }
732 | }
733 | ],
734 | "requestBody": {
735 | "content": {
736 | "application/json": {
737 | "schema": {
738 | "allOf": [
739 | {
740 | "$ref": "#/components/schemas/SendSecurityCodeToUserEmailRequest"
741 | }
742 | ]
743 | }
744 | }
745 | }
746 | },
747 | "responses": {
748 | "401": {
749 | "description": "Device certificate expired.",
750 | "headers": {
751 | "operationId": {
752 | "description": "unique operation id",
753 | "schema": {
754 | "type": "string",
755 | "description": "unique operation id",
756 | "format": ""
757 | }
758 | }
759 | },
760 | "content": {
761 | "application/problem+json": {
762 | "schema": {
763 | "$ref": "#/components/schemas/ProblemDetails"
764 | }
765 | }
766 | }
767 | },
768 | "500": {
769 | "description": "Server encountered temporary issues.",
770 | "headers": {
771 | "operationId": {
772 | "description": "unique operation id",
773 | "schema": {
774 | "type": "string",
775 | "description": "unique operation id",
776 | "format": ""
777 | }
778 | }
779 | },
780 | "content": {
781 | "application/problem+json": {
782 | "schema": {
783 | "$ref": "#/components/schemas/ProblemDetails"
784 | },
785 | "example": {
786 | "type": "https://httpstatuses.io/500",
787 | "title": "Server error",
788 | "status": 500,
789 | "operationID": "0HMPDRRQL1C0G:00000005"
790 | }
791 | }
792 | }
793 | },
794 | "200": {
795 | "description": "Success",
796 | "headers": {
797 | "operationId": {
798 | "description": "unique operation id",
799 | "schema": {
800 | "type": "string",
801 | "description": "unique operation id",
802 | "format": ""
803 | }
804 | }
805 | },
806 | "content": {
807 | "application/json": {
808 | "schema": {
809 | "$ref": "#/components/schemas/SendSecurityCodeToUserEmailResponse"
810 | }
811 | }
812 | }
813 | },
814 | "400": {
815 | "description": "Bad Request",
816 | "headers": {
817 | "operationId": {
818 | "description": "unique operation id",
819 | "schema": {
820 | "type": "string",
821 | "description": "unique operation id",
822 | "format": ""
823 | }
824 | }
825 | },
826 | "content": {
827 | "application/problem+json": {
828 | "schema": {
829 | "$ref": "#/components/schemas/ValidationProblemDetails"
830 | }
831 | }
832 | }
833 | },
834 | "422": {
835 | "description": "Operation failed because of provided data or invalid object state in Fiscal backend. Returns problem details structure as described in https://www.rfc-editor.org/rfc/rfc7807 with errorCode field to specify error.",
836 | "headers": {
837 | "operationId": {
838 | "description": "unique operation id",
839 | "schema": {
840 | "type": "string",
841 | "description": "unique operation id",
842 | "format": ""
843 | }
844 | }
845 | },
846 | "content": {
847 | "application/problem+json": {
848 | "schema": {
849 | "$ref": "#/components/schemas/ApiProblemDetails"
850 | }
851 | }
852 | }
853 | }
854 | }
855 | }
856 | },
857 | "/User/v1/{deviceID}/SendSecurityCodeToUserPhone": {
858 | "post": {
859 | "tags": [
860 | "User"
861 | ],
862 | "description": "Sends security code to confirm user phone",
863 | "parameters": [
864 | {
865 | "name": "Token",
866 | "in": "header",
867 | "required": true,
868 | "schema": {
869 | "type": "string"
870 | }
871 | },
872 | {
873 | "name": "deviceID",
874 | "in": "path",
875 | "required": true,
876 | "schema": {
877 | "type": "integer",
878 | "format": "int32"
879 | }
880 | },
881 | {
882 | "name": "DeviceModelName",
883 | "in": "header",
884 | "description": "Device model name as registered in Tax Authority",
885 | "schema": {
886 | "type": "string"
887 | }
888 | },
889 | {
890 | "name": "DeviceModelVersion",
891 | "in": "header",
892 | "description": "Device model version number as registered in Tax Authority",
893 | "schema": {
894 | "type": "string"
895 | }
896 | }
897 | ],
898 | "requestBody": {
899 | "content": {
900 | "application/json": {
901 | "schema": {
902 | "allOf": [
903 | {
904 | "$ref": "#/components/schemas/SendSecurityCodeToUserPhoneRequest"
905 | }
906 | ]
907 | }
908 | }
909 | }
910 | },
911 | "responses": {
912 | "401": {
913 | "description": "Device certificate expired.",
914 | "headers": {
915 | "operationId": {
916 | "description": "unique operation id",
917 | "schema": {
918 | "type": "string",
919 | "description": "unique operation id",
920 | "format": ""
921 | }
922 | }
923 | },
924 | "content": {
925 | "application/problem+json": {
926 | "schema": {
927 | "$ref": "#/components/schemas/ProblemDetails"
928 | }
929 | }
930 | }
931 | },
932 | "500": {
933 | "description": "Server encountered temporary issues.",
934 | "headers": {
935 | "operationId": {
936 | "description": "unique operation id",
937 | "schema": {
938 | "type": "string",
939 | "description": "unique operation id",
940 | "format": ""
941 | }
942 | }
943 | },
944 | "content": {
945 | "application/problem+json": {
946 | "schema": {
947 | "$ref": "#/components/schemas/ProblemDetails"
948 | },
949 | "example": {
950 | "type": "https://httpstatuses.io/500",
951 | "title": "Server error",
952 | "status": 500,
953 | "operationID": "0HMPDRRQL1C0G:00000005"
954 | }
955 | }
956 | }
957 | },
958 | "200": {
959 | "description": "Success",
960 | "headers": {
961 | "operationId": {
962 | "description": "unique operation id",
963 | "schema": {
964 | "type": "string",
965 | "description": "unique operation id",
966 | "format": ""
967 | }
968 | }
969 | },
970 | "content": {
971 | "application/json": {
972 | "schema": {
973 | "$ref": "#/components/schemas/SendSecurityCodeToUserPhoneResponse"
974 | }
975 | }
976 | }
977 | },
978 | "400": {
979 | "description": "Bad Request",
980 | "headers": {
981 | "operationId": {
982 | "description": "unique operation id",
983 | "schema": {
984 | "type": "string",
985 | "description": "unique operation id",
986 | "format": ""
987 | }
988 | }
989 | },
990 | "content": {
991 | "application/problem+json": {
992 | "schema": {
993 | "$ref": "#/components/schemas/ValidationProblemDetails"
994 | }
995 | }
996 | }
997 | },
998 | "422": {
999 | "description": "Operation failed because of provided data or invalid object state in Fiscal backend. Returns problem details structure as described in https://www.rfc-editor.org/rfc/rfc7807 with errorCode field to specify error.",
1000 | "headers": {
1001 | "operationId": {
1002 | "description": "unique operation id",
1003 | "schema": {
1004 | "type": "string",
1005 | "description": "unique operation id",
1006 | "format": ""
1007 | }
1008 | }
1009 | },
1010 | "content": {
1011 | "application/problem+json": {
1012 | "schema": {
1013 | "$ref": "#/components/schemas/ApiProblemDetails"
1014 | }
1015 | }
1016 | }
1017 | }
1018 | }
1019 | }
1020 | },
1021 | "/User/v1/{deviceID}/ConfirmUser": {
1022 | "post": {
1023 | "tags": [
1024 | "User"
1025 | ],
1026 | "description": "Endpoint is user creation confirmation by taxpayer.",
1027 | "parameters": [
1028 | {
1029 | "name": "deviceID",
1030 | "in": "path",
1031 | "required": true,
1032 | "schema": {
1033 | "type": "integer",
1034 | "format": "int32"
1035 | }
1036 | },
1037 | {
1038 | "name": "DeviceModelName",
1039 | "in": "header",
1040 | "description": "Device model name as registered in Tax Authority",
1041 | "schema": {
1042 | "type": "string"
1043 | }
1044 | },
1045 | {
1046 | "name": "DeviceModelVersion",
1047 | "in": "header",
1048 | "description": "Device model version number as registered in Tax Authority",
1049 | "schema": {
1050 | "type": "string"
1051 | }
1052 | }
1053 | ],
1054 | "requestBody": {
1055 | "description": "",
1056 | "content": {
1057 | "application/json": {
1058 | "schema": {
1059 | "allOf": [
1060 | {
1061 | "$ref": "#/components/schemas/ConfirmUserRequest"
1062 | }
1063 | ]
1064 | }
1065 | }
1066 | }
1067 | },
1068 | "responses": {
1069 | "401": {
1070 | "description": "Device certificate expired.",
1071 | "headers": {
1072 | "operationId": {
1073 | "description": "unique operation id",
1074 | "schema": {
1075 | "type": "string",
1076 | "description": "unique operation id",
1077 | "format": ""
1078 | }
1079 | }
1080 | },
1081 | "content": {
1082 | "application/problem+json": {
1083 | "schema": {
1084 | "$ref": "#/components/schemas/ProblemDetails"
1085 | }
1086 | }
1087 | }
1088 | },
1089 | "500": {
1090 | "description": "Server encountered temporary issues.",
1091 | "headers": {
1092 | "operationId": {
1093 | "description": "unique operation id",
1094 | "schema": {
1095 | "type": "string",
1096 | "description": "unique operation id",
1097 | "format": ""
1098 | }
1099 | }
1100 | },
1101 | "content": {
1102 | "application/problem+json": {
1103 | "schema": {
1104 | "$ref": "#/components/schemas/ProblemDetails"
1105 | },
1106 | "example": {
1107 | "type": "https://httpstatuses.io/500",
1108 | "title": "Server error",
1109 | "status": 500,
1110 | "operationID": "0HMPDRRQL1C0G:00000005"
1111 | }
1112 | }
1113 | }
1114 | },
1115 | "200": {
1116 | "description": "Success",
1117 | "headers": {
1118 | "operationId": {
1119 | "description": "unique operation id",
1120 | "schema": {
1121 | "type": "string",
1122 | "description": "unique operation id",
1123 | "format": ""
1124 | }
1125 | }
1126 | },
1127 | "content": {
1128 | "application/json": {
1129 | "schema": {
1130 | "$ref": "#/components/schemas/LoginResponse"
1131 | }
1132 | }
1133 | }
1134 | },
1135 | "400": {
1136 | "description": "Bad Request",
1137 | "headers": {
1138 | "operationId": {
1139 | "description": "unique operation id",
1140 | "schema": {
1141 | "type": "string",
1142 | "description": "unique operation id",
1143 | "format": ""
1144 | }
1145 | }
1146 | },
1147 | "content": {
1148 | "application/problem+json": {
1149 | "schema": {
1150 | "$ref": "#/components/schemas/ValidationProblemDetails"
1151 | }
1152 | }
1153 | }
1154 | },
1155 | "422": {
1156 | "description": "Operation failed because of provided data or invalid object state in Fiscal backend. Returns problem details structure as described in https://www.rfc-editor.org/rfc/rfc7807 with errorCode field to specify error.",
1157 | "headers": {
1158 | "operationId": {
1159 | "description": "unique operation id",
1160 | "schema": {
1161 | "type": "string",
1162 | "description": "unique operation id",
1163 | "format": ""
1164 | }
1165 | }
1166 | },
1167 | "content": {
1168 | "application/problem+json": {
1169 | "schema": {
1170 | "$ref": "#/components/schemas/ApiProblemDetails"
1171 | }
1172 | }
1173 | }
1174 | }
1175 | }
1176 | }
1177 | },
1178 | "/User/v1/{deviceID}/ChangePassword": {
1179 | "post": {
1180 | "tags": [
1181 | "User"
1182 | ],
1183 | "description": "Endpoint is used to change user password.",
1184 | "parameters": [
1185 | {
1186 | "name": "Token",
1187 | "in": "header",
1188 | "description": "",
1189 | "required": true,
1190 | "schema": {
1191 | "type": "string"
1192 | }
1193 | },
1194 | {
1195 | "name": "deviceID",
1196 | "in": "path",
1197 | "required": true,
1198 | "schema": {
1199 | "type": "integer",
1200 | "format": "int32"
1201 | }
1202 | },
1203 | {
1204 | "name": "DeviceModelName",
1205 | "in": "header",
1206 | "description": "Device model name as registered in Tax Authority",
1207 | "schema": {
1208 | "type": "string"
1209 | }
1210 | },
1211 | {
1212 | "name": "DeviceModelVersion",
1213 | "in": "header",
1214 | "description": "Device model version number as registered in Tax Authority",
1215 | "schema": {
1216 | "type": "string"
1217 | }
1218 | }
1219 | ],
1220 | "requestBody": {
1221 | "description": "",
1222 | "content": {
1223 | "application/json": {
1224 | "schema": {
1225 | "allOf": [
1226 | {
1227 | "$ref": "#/components/schemas/ChangePasswordRequest"
1228 | }
1229 | ]
1230 | }
1231 | }
1232 | }
1233 | },
1234 | "responses": {
1235 | "401": {
1236 | "description": "Device certificate expired.",
1237 | "headers": {
1238 | "operationId": {
1239 | "description": "unique operation id",
1240 | "schema": {
1241 | "type": "string",
1242 | "description": "unique operation id",
1243 | "format": ""
1244 | }
1245 | }
1246 | },
1247 | "content": {
1248 | "application/problem+json": {
1249 | "schema": {
1250 | "$ref": "#/components/schemas/ProblemDetails"
1251 | }
1252 | }
1253 | }
1254 | },
1255 | "500": {
1256 | "description": "Server encountered temporary issues.",
1257 | "headers": {
1258 | "operationId": {
1259 | "description": "unique operation id",
1260 | "schema": {
1261 | "type": "string",
1262 | "description": "unique operation id",
1263 | "format": ""
1264 | }
1265 | }
1266 | },
1267 | "content": {
1268 | "application/problem+json": {
1269 | "schema": {
1270 | "$ref": "#/components/schemas/ProblemDetails"
1271 | },
1272 | "example": {
1273 | "type": "https://httpstatuses.io/500",
1274 | "title": "Server error",
1275 | "status": 500,
1276 | "operationID": "0HMPDRRQL1C0G:00000005"
1277 | }
1278 | }
1279 | }
1280 | },
1281 | "200": {
1282 | "description": "Success",
1283 | "headers": {
1284 | "operationId": {
1285 | "description": "unique operation id",
1286 | "schema": {
1287 | "type": "string",
1288 | "description": "unique operation id",
1289 | "format": ""
1290 | }
1291 | }
1292 | },
1293 | "content": {
1294 | "application/json": {
1295 | "schema": {
1296 | "$ref": "#/components/schemas/LoginResponse"
1297 | }
1298 | }
1299 | }
1300 | },
1301 | "400": {
1302 | "description": "Bad Request",
1303 | "headers": {
1304 | "operationId": {
1305 | "description": "unique operation id",
1306 | "schema": {
1307 | "type": "string",
1308 | "description": "unique operation id",
1309 | "format": ""
1310 | }
1311 | }
1312 | },
1313 | "content": {
1314 | "application/problem+json": {
1315 | "schema": {
1316 | "$ref": "#/components/schemas/ValidationProblemDetails"
1317 | }
1318 | }
1319 | }
1320 | },
1321 | "422": {
1322 | "description": "Operation failed because of provided data or invalid object state in Fiscal backend. Returns problem details structure as described in https://www.rfc-editor.org/rfc/rfc7807 with errorCode field to specify error.",
1323 | "headers": {
1324 | "operationId": {
1325 | "description": "unique operation id",
1326 | "schema": {
1327 | "type": "string",
1328 | "description": "unique operation id",
1329 | "format": ""
1330 | }
1331 | }
1332 | },
1333 | "content": {
1334 | "application/problem+json": {
1335 | "schema": {
1336 | "$ref": "#/components/schemas/ApiProblemDetails"
1337 | }
1338 | }
1339 | }
1340 | }
1341 | }
1342 | }
1343 | },
1344 | "/User/v1/{deviceID}/ResetPassword": {
1345 | "post": {
1346 | "tags": [
1347 | "User"
1348 | ],
1349 | "description": "Endpoint is used to change user password.",
1350 | "parameters": [
1351 | {
1352 | "name": "deviceID",
1353 | "in": "path",
1354 | "required": true,
1355 | "schema": {
1356 | "type": "integer",
1357 | "format": "int32"
1358 | }
1359 | },
1360 | {
1361 | "name": "DeviceModelName",
1362 | "in": "header",
1363 | "description": "Device model name as registered in Tax Authority",
1364 | "schema": {
1365 | "type": "string"
1366 | }
1367 | },
1368 | {
1369 | "name": "DeviceModelVersion",
1370 | "in": "header",
1371 | "description": "Device model version number as registered in Tax Authority",
1372 | "schema": {
1373 | "type": "string"
1374 | }
1375 | }
1376 | ],
1377 | "requestBody": {
1378 | "description": "",
1379 | "content": {
1380 | "application/json": {
1381 | "schema": {
1382 | "allOf": [
1383 | {
1384 | "$ref": "#/components/schemas/ResetPasswordRequest"
1385 | }
1386 | ]
1387 | }
1388 | }
1389 | }
1390 | },
1391 | "responses": {
1392 | "401": {
1393 | "description": "Device certificate expired.",
1394 | "headers": {
1395 | "operationId": {
1396 | "description": "unique operation id",
1397 | "schema": {
1398 | "type": "string",
1399 | "description": "unique operation id",
1400 | "format": ""
1401 | }
1402 | }
1403 | },
1404 | "content": {
1405 | "application/problem+json": {
1406 | "schema": {
1407 | "$ref": "#/components/schemas/ProblemDetails"
1408 | }
1409 | }
1410 | }
1411 | },
1412 | "500": {
1413 | "description": "Server encountered temporary issues.",
1414 | "headers": {
1415 | "operationId": {
1416 | "description": "unique operation id",
1417 | "schema": {
1418 | "type": "string",
1419 | "description": "unique operation id",
1420 | "format": ""
1421 | }
1422 | }
1423 | },
1424 | "content": {
1425 | "application/problem+json": {
1426 | "schema": {
1427 | "$ref": "#/components/schemas/ProblemDetails"
1428 | },
1429 | "example": {
1430 | "type": "https://httpstatuses.io/500",
1431 | "title": "Server error",
1432 | "status": 500,
1433 | "operationID": "0HMPDRRQL1C0G:00000005"
1434 | }
1435 | }
1436 | }
1437 | },
1438 | "200": {
1439 | "description": "Success",
1440 | "headers": {
1441 | "operationId": {
1442 | "description": "unique operation id",
1443 | "schema": {
1444 | "type": "string",
1445 | "description": "unique operation id",
1446 | "format": ""
1447 | }
1448 | }
1449 | },
1450 | "content": {
1451 | "application/json": {
1452 | "schema": {
1453 | "$ref": "#/components/schemas/ResetPasswordResponse"
1454 | }
1455 | }
1456 | }
1457 | },
1458 | "400": {
1459 | "description": "Bad Request",
1460 | "headers": {
1461 | "operationId": {
1462 | "description": "unique operation id",
1463 | "schema": {
1464 | "type": "string",
1465 | "description": "unique operation id",
1466 | "format": ""
1467 | }
1468 | }
1469 | },
1470 | "content": {
1471 | "application/problem+json": {
1472 | "schema": {
1473 | "$ref": "#/components/schemas/ValidationProblemDetails"
1474 | }
1475 | }
1476 | }
1477 | },
1478 | "422": {
1479 | "description": "Operation failed because of provided data or invalid object state in Fiscal backend. Returns problem details structure as described in https://www.rfc-editor.org/rfc/rfc7807 with errorCode field to specify error.",
1480 | "headers": {
1481 | "operationId": {
1482 | "description": "unique operation id",
1483 | "schema": {
1484 | "type": "string",
1485 | "description": "unique operation id",
1486 | "format": ""
1487 | }
1488 | }
1489 | },
1490 | "content": {
1491 | "application/problem+json": {
1492 | "schema": {
1493 | "$ref": "#/components/schemas/ApiProblemDetails"
1494 | }
1495 | }
1496 | }
1497 | }
1498 | }
1499 | }
1500 | },
1501 | "/User/v1/{deviceID}/ConfirmContact": {
1502 | "post": {
1503 | "tags": [
1504 | "User"
1505 | ],
1506 | "description": "Endpoint is used for user contact change confirmation.",
1507 | "parameters": [
1508 | {
1509 | "name": "Token",
1510 | "in": "header",
1511 | "description": "",
1512 | "required": true,
1513 | "schema": {
1514 | "type": "string"
1515 | }
1516 | },
1517 | {
1518 | "name": "deviceID",
1519 | "in": "path",
1520 | "required": true,
1521 | "schema": {
1522 | "type": "integer",
1523 | "format": "int32"
1524 | }
1525 | },
1526 | {
1527 | "name": "DeviceModelName",
1528 | "in": "header",
1529 | "description": "Device model name as registered in Tax Authority",
1530 | "schema": {
1531 | "type": "string"
1532 | }
1533 | },
1534 | {
1535 | "name": "DeviceModelVersion",
1536 | "in": "header",
1537 | "description": "Device model version number as registered in Tax Authority",
1538 | "schema": {
1539 | "type": "string"
1540 | }
1541 | }
1542 | ],
1543 | "requestBody": {
1544 | "description": "",
1545 | "content": {
1546 | "application/json": {
1547 | "schema": {
1548 | "allOf": [
1549 | {
1550 | "$ref": "#/components/schemas/ConfirmContactRequest"
1551 | }
1552 | ]
1553 | }
1554 | }
1555 | }
1556 | },
1557 | "responses": {
1558 | "401": {
1559 | "description": "Device certificate expired.",
1560 | "headers": {
1561 | "operationId": {
1562 | "description": "unique operation id",
1563 | "schema": {
1564 | "type": "string",
1565 | "description": "unique operation id",
1566 | "format": ""
1567 | }
1568 | }
1569 | },
1570 | "content": {
1571 | "application/problem+json": {
1572 | "schema": {
1573 | "$ref": "#/components/schemas/ProblemDetails"
1574 | }
1575 | }
1576 | }
1577 | },
1578 | "500": {
1579 | "description": "Server encountered temporary issues.",
1580 | "headers": {
1581 | "operationId": {
1582 | "description": "unique operation id",
1583 | "schema": {
1584 | "type": "string",
1585 | "description": "unique operation id",
1586 | "format": ""
1587 | }
1588 | }
1589 | },
1590 | "content": {
1591 | "application/problem+json": {
1592 | "schema": {
1593 | "$ref": "#/components/schemas/ProblemDetails"
1594 | },
1595 | "example": {
1596 | "type": "https://httpstatuses.io/500",
1597 | "title": "Server error",
1598 | "status": 500,
1599 | "operationID": "0HMPDRRQL1C0G:00000005"
1600 | }
1601 | }
1602 | }
1603 | },
1604 | "200": {
1605 | "description": "Success",
1606 | "headers": {
1607 | "operationId": {
1608 | "description": "unique operation id",
1609 | "schema": {
1610 | "type": "string",
1611 | "description": "unique operation id",
1612 | "format": ""
1613 | }
1614 | }
1615 | },
1616 | "content": {
1617 | "application/json": {
1618 | "schema": {
1619 | "$ref": "#/components/schemas/ConfirmContactResponse"
1620 | }
1621 | }
1622 | }
1623 | },
1624 | "400": {
1625 | "description": "Bad Request",
1626 | "headers": {
1627 | "operationId": {
1628 | "description": "unique operation id",
1629 | "schema": {
1630 | "type": "string",
1631 | "description": "unique operation id",
1632 | "format": ""
1633 | }
1634 | }
1635 | },
1636 | "content": {
1637 | "application/problem+json": {
1638 | "schema": {
1639 | "$ref": "#/components/schemas/ValidationProblemDetails"
1640 | }
1641 | }
1642 | }
1643 | },
1644 | "422": {
1645 | "description": "Operation failed because of provided data or invalid object state in Fiscal backend. Returns problem details structure as described in https://www.rfc-editor.org/rfc/rfc7807 with errorCode field to specify error.",
1646 | "headers": {
1647 | "operationId": {
1648 | "description": "unique operation id",
1649 | "schema": {
1650 | "type": "string",
1651 | "description": "unique operation id",
1652 | "format": ""
1653 | }
1654 | }
1655 | },
1656 | "content": {
1657 | "application/problem+json": {
1658 | "schema": {
1659 | "$ref": "#/components/schemas/ApiProblemDetails"
1660 | }
1661 | }
1662 | }
1663 | }
1664 | }
1665 | }
1666 | },
1667 | "/User/v1/{deviceID}/Update": {
1668 | "post": {
1669 | "tags": [
1670 | "User"
1671 | ],
1672 | "description": "Endpoint is used to update user.",
1673 | "parameters": [
1674 | {
1675 | "name": "Token",
1676 | "in": "header",
1677 | "description": "",
1678 | "required": true,
1679 | "schema": {
1680 | "type": "string"
1681 | }
1682 | },
1683 | {
1684 | "name": "deviceID",
1685 | "in": "path",
1686 | "required": true,
1687 | "schema": {
1688 | "type": "integer",
1689 | "format": "int32"
1690 | }
1691 | },
1692 | {
1693 | "name": "DeviceModelName",
1694 | "in": "header",
1695 | "description": "Device model name as registered in Tax Authority",
1696 | "schema": {
1697 | "type": "string"
1698 | }
1699 | },
1700 | {
1701 | "name": "DeviceModelVersion",
1702 | "in": "header",
1703 | "description": "Device model version number as registered in Tax Authority",
1704 | "schema": {
1705 | "type": "string"
1706 | }
1707 | }
1708 | ],
1709 | "requestBody": {
1710 | "description": "",
1711 | "content": {
1712 | "application/json": {
1713 | "schema": {
1714 | "allOf": [
1715 | {
1716 | "$ref": "#/components/schemas/UpdateUserRequest"
1717 | }
1718 | ]
1719 | }
1720 | }
1721 | }
1722 | },
1723 | "responses": {
1724 | "401": {
1725 | "description": "Device certificate expired.",
1726 | "headers": {
1727 | "operationId": {
1728 | "description": "unique operation id",
1729 | "schema": {
1730 | "type": "string",
1731 | "description": "unique operation id",
1732 | "format": ""
1733 | }
1734 | }
1735 | },
1736 | "content": {
1737 | "application/problem+json": {
1738 | "schema": {
1739 | "$ref": "#/components/schemas/ProblemDetails"
1740 | }
1741 | }
1742 | }
1743 | },
1744 | "500": {
1745 | "description": "Server encountered temporary issues.",
1746 | "headers": {
1747 | "operationId": {
1748 | "description": "unique operation id",
1749 | "schema": {
1750 | "type": "string",
1751 | "description": "unique operation id",
1752 | "format": ""
1753 | }
1754 | }
1755 | },
1756 | "content": {
1757 | "application/problem+json": {
1758 | "schema": {
1759 | "$ref": "#/components/schemas/ProblemDetails"
1760 | },
1761 | "example": {
1762 | "type": "https://httpstatuses.io/500",
1763 | "title": "Server error",
1764 | "status": 500,
1765 | "operationID": "0HMPDRRQL1C0G:00000005"
1766 | }
1767 | }
1768 | }
1769 | },
1770 | "200": {
1771 | "description": "Success",
1772 | "headers": {
1773 | "operationId": {
1774 | "description": "unique operation id",
1775 | "schema": {
1776 | "type": "string",
1777 | "description": "unique operation id",
1778 | "format": ""
1779 | }
1780 | }
1781 | },
1782 | "content": {
1783 | "application/json": {
1784 | "schema": {
1785 | "$ref": "#/components/schemas/UpdateUserResponse"
1786 | }
1787 | }
1788 | }
1789 | },
1790 | "400": {
1791 | "description": "Bad Request",
1792 | "headers": {
1793 | "operationId": {
1794 | "description": "unique operation id",
1795 | "schema": {
1796 | "type": "string",
1797 | "description": "unique operation id",
1798 | "format": ""
1799 | }
1800 | }
1801 | },
1802 | "content": {
1803 | "application/problem+json": {
1804 | "schema": {
1805 | "$ref": "#/components/schemas/ValidationProblemDetails"
1806 | }
1807 | }
1808 | }
1809 | },
1810 | "422": {
1811 | "description": "Operation failed because of provided data or invalid object state in Fiscal backend. Returns problem details structure as described in https://www.rfc-editor.org/rfc/rfc7807 with errorCode field to specify error.",
1812 | "headers": {
1813 | "operationId": {
1814 | "description": "unique operation id",
1815 | "schema": {
1816 | "type": "string",
1817 | "description": "unique operation id",
1818 | "format": ""
1819 | }
1820 | }
1821 | },
1822 | "content": {
1823 | "application/problem+json": {
1824 | "schema": {
1825 | "$ref": "#/components/schemas/ApiProblemDetails"
1826 | }
1827 | }
1828 | }
1829 | }
1830 | }
1831 | }
1832 | },
1833 | "/User/v1/{deviceID}/ConfirmPasswordReset": {
1834 | "post": {
1835 | "tags": [
1836 | "User"
1837 | ],
1838 | "summary": "Endpoint for confirming password reset",
1839 | "parameters": [
1840 | {
1841 | "name": "deviceID",
1842 | "in": "path",
1843 | "required": true,
1844 | "schema": {
1845 | "type": "integer",
1846 | "format": "int32"
1847 | }
1848 | },
1849 | {
1850 | "name": "DeviceModelName",
1851 | "in": "header",
1852 | "description": "Device model name as registered in Tax Authority",
1853 | "schema": {
1854 | "type": "string"
1855 | }
1856 | },
1857 | {
1858 | "name": "DeviceModelVersion",
1859 | "in": "header",
1860 | "description": "Device model version number as registered in Tax Authority",
1861 | "schema": {
1862 | "type": "string"
1863 | }
1864 | }
1865 | ],
1866 | "requestBody": {
1867 | "description": "",
1868 | "content": {
1869 | "application/json": {
1870 | "schema": {
1871 | "allOf": [
1872 | {
1873 | "$ref": "#/components/schemas/ConfirmPasswordResetRequest"
1874 | }
1875 | ]
1876 | }
1877 | }
1878 | }
1879 | },
1880 | "responses": {
1881 | "401": {
1882 | "description": "Device certificate expired.",
1883 | "headers": {
1884 | "operationId": {
1885 | "description": "unique operation id",
1886 | "schema": {
1887 | "type": "string",
1888 | "description": "unique operation id",
1889 | "format": ""
1890 | }
1891 | }
1892 | },
1893 | "content": {
1894 | "application/problem+json": {
1895 | "schema": {
1896 | "$ref": "#/components/schemas/ProblemDetails"
1897 | }
1898 | }
1899 | }
1900 | },
1901 | "500": {
1902 | "description": "Server encountered temporary issues.",
1903 | "headers": {
1904 | "operationId": {
1905 | "description": "unique operation id",
1906 | "schema": {
1907 | "type": "string",
1908 | "description": "unique operation id",
1909 | "format": ""
1910 | }
1911 | }
1912 | },
1913 | "content": {
1914 | "application/problem+json": {
1915 | "schema": {
1916 | "$ref": "#/components/schemas/ProblemDetails"
1917 | },
1918 | "example": {
1919 | "type": "https://httpstatuses.io/500",
1920 | "title": "Server error",
1921 | "status": 500,
1922 | "operationID": "0HMPDRRQL1C0G:00000005"
1923 | }
1924 | }
1925 | }
1926 | },
1927 | "200": {
1928 | "description": "Success",
1929 | "headers": {
1930 | "operationId": {
1931 | "description": "unique operation id",
1932 | "schema": {
1933 | "type": "string",
1934 | "description": "unique operation id",
1935 | "format": ""
1936 | }
1937 | }
1938 | },
1939 | "content": {
1940 | "application/json": {
1941 | "schema": {
1942 | "$ref": "#/components/schemas/LoginResponse"
1943 | }
1944 | }
1945 | }
1946 | },
1947 | "400": {
1948 | "description": "Bad Request",
1949 | "headers": {
1950 | "operationId": {
1951 | "description": "unique operation id",
1952 | "schema": {
1953 | "type": "string",
1954 | "description": "unique operation id",
1955 | "format": ""
1956 | }
1957 | }
1958 | },
1959 | "content": {
1960 | "application/problem+json": {
1961 | "schema": {
1962 | "$ref": "#/components/schemas/ValidationProblemDetails"
1963 | }
1964 | }
1965 | }
1966 | },
1967 | "422": {
1968 | "description": "Operation failed because of provided data or invalid object state in Fiscal backend. Returns problem details structure as described in https://www.rfc-editor.org/rfc/rfc7807 with errorCode field to specify error.",
1969 | "headers": {
1970 | "operationId": {
1971 | "description": "unique operation id",
1972 | "schema": {
1973 | "type": "string",
1974 | "description": "unique operation id",
1975 | "format": ""
1976 | }
1977 | }
1978 | },
1979 | "content": {
1980 | "application/problem+json": {
1981 | "schema": {
1982 | "$ref": "#/components/schemas/ApiProblemDetails"
1983 | }
1984 | }
1985 | }
1986 | }
1987 | }
1988 | }
1989 | }
1990 | },
1991 | "components": {
1992 | "schemas": {
1993 | "ApiProblemDetails": {
1994 | "type": "object",
1995 | "properties": {
1996 | "type": {
1997 | "type": "string",
1998 | "nullable": true
1999 | },
2000 | "title": {
2001 | "type": "string",
2002 | "nullable": true
2003 | },
2004 | "status": {
2005 | "type": "integer",
2006 | "format": "int32",
2007 | "nullable": true
2008 | },
2009 | "detail": {
2010 | "type": "string",
2011 | "nullable": true
2012 | },
2013 | "instance": {
2014 | "type": "string",
2015 | "nullable": true
2016 | },
2017 | "errorCode": {
2018 | "type": "string",
2019 | "nullable": true
2020 | }
2021 | },
2022 | "additionalProperties": { }
2023 | },
2024 | "ChangePasswordRequest": {
2025 | "required": [
2026 | "newPassword",
2027 | "oldPassword"
2028 | ],
2029 | "type": "object",
2030 | "properties": {
2031 | "oldPassword": {
2032 | "maxLength": 100,
2033 | "minLength": 1,
2034 | "type": "string"
2035 | },
2036 | "newPassword": {
2037 | "maxLength": 100,
2038 | "minLength": 1,
2039 | "type": "string"
2040 | }
2041 | },
2042 | "additionalProperties": false
2043 | },
2044 | "ConfirmContactRequest": {
2045 | "required": [
2046 | "channel",
2047 | "securityCode"
2048 | ],
2049 | "type": "object",
2050 | "properties": {
2051 | "securityCode": {
2052 | "maxLength": 10,
2053 | "minLength": 1,
2054 | "type": "string"
2055 | },
2056 | "channel": {
2057 | "allOf": [
2058 | {
2059 | "$ref": "#/components/schemas/SendSecurityCodeToEnum"
2060 | }
2061 | ]
2062 | }
2063 | },
2064 | "additionalProperties": false
2065 | },
2066 | "ConfirmContactResponse": {
2067 | "required": [
2068 | "operationID",
2069 | "user"
2070 | ],
2071 | "type": "object",
2072 | "properties": {
2073 | "operationID": {
2074 | "maxLength": 60,
2075 | "minLength": 0,
2076 | "type": "string",
2077 | "description": "Operation ID assigned by Fiscalisation Backend.",
2078 | "example": "0HMPH9AF0QKKE:00000005"
2079 | },
2080 | "user": {
2081 | "allOf": [
2082 | {
2083 | "$ref": "#/components/schemas/UserDto"
2084 | }
2085 | ]
2086 | }
2087 | },
2088 | "additionalProperties": false
2089 | },
2090 | "ConfirmPasswordResetRequest": {
2091 | "required": [
2092 | "newPassword",
2093 | "securityCode",
2094 | "userName"
2095 | ],
2096 | "type": "object",
2097 | "properties": {
2098 | "userName": {
2099 | "maxLength": 100,
2100 | "minLength": 1,
2101 | "type": "string"
2102 | },
2103 | "securityCode": {
2104 | "maxLength": 10,
2105 | "minLength": 1,
2106 | "type": "string"
2107 | },
2108 | "newPassword": {
2109 | "maxLength": 100,
2110 | "minLength": 1,
2111 | "type": "string"
2112 | }
2113 | },
2114 | "additionalProperties": false
2115 | },
2116 | "ConfirmUserRequest": {
2117 | "required": [
2118 | "password",
2119 | "securityCode",
2120 | "userName"
2121 | ],
2122 | "type": "object",
2123 | "properties": {
2124 | "userName": {
2125 | "maxLength": 100,
2126 | "minLength": 1,
2127 | "type": "string"
2128 | },
2129 | "securityCode": {
2130 | "maxLength": 10,
2131 | "minLength": 1,
2132 | "type": "string"
2133 | },
2134 | "password": {
2135 | "maxLength": 100,
2136 | "minLength": 1,
2137 | "type": "string"
2138 | }
2139 | },
2140 | "additionalProperties": false
2141 | },
2142 | "CreateUserRequest": {
2143 | "required": [
2144 | "personName",
2145 | "personSurname",
2146 | "userName",
2147 | "userRole"
2148 | ],
2149 | "type": "object",
2150 | "properties": {
2151 | "userName": {
2152 | "maxLength": 100,
2153 | "minLength": 1,
2154 | "type": "string"
2155 | },
2156 | "personName": {
2157 | "maxLength": 100,
2158 | "minLength": 1,
2159 | "type": "string"
2160 | },
2161 | "personSurname": {
2162 | "maxLength": 100,
2163 | "minLength": 1,
2164 | "type": "string"
2165 | },
2166 | "userRole": {
2167 | "maxLength": 100,
2168 | "minLength": 1,
2169 | "type": "string"
2170 | }
2171 | },
2172 | "additionalProperties": false
2173 | },
2174 | "CreateUserResponse": {
2175 | "required": [
2176 | "operationID"
2177 | ],
2178 | "type": "object",
2179 | "properties": {
2180 | "operationID": {
2181 | "maxLength": 60,
2182 | "minLength": 0,
2183 | "type": "string",
2184 | "description": "Operation ID assigned by Fiscalisation Backend.",
2185 | "example": "0HMPH9AF0QKKE:00000005"
2186 | }
2187 | },
2188 | "additionalProperties": false
2189 | },
2190 | "GetUsersListEnum": {
2191 | "enum": [
2192 | "UserName",
2193 | "PersonName",
2194 | "PersonSurname",
2195 | "UserRole",
2196 | "Email",
2197 | "PhoneNo",
2198 | "UserStatus"
2199 | ],
2200 | "type": "string"
2201 | },
2202 | "GetUsersResponse": {
2203 | "required": [
2204 | "operationID"
2205 | ],
2206 | "type": "object",
2207 | "properties": {
2208 | "total": {
2209 | "type": "integer",
2210 | "format": "int32"
2211 | },
2212 | "rows": {
2213 | "type": "array",
2214 | "items": {
2215 | "$ref": "#/components/schemas/UsersListDto"
2216 | },
2217 | "nullable": true
2218 | },
2219 | "operationID": {
2220 | "maxLength": 60,
2221 | "minLength": 0,
2222 | "type": "string",
2223 | "description": "Operation ID assigned by Fiscalisation Backend.",
2224 | "example": "0HMPH9AF0QKKE:00000005"
2225 | }
2226 | },
2227 | "additionalProperties": false
2228 | },
2229 | "ListRequestOrderEnum": {
2230 | "enum": [
2231 | "asc",
2232 | "desc"
2233 | ],
2234 | "type": "string"
2235 | },
2236 | "LogicalOperator": {
2237 | "enum": [
2238 | "And",
2239 | "Or"
2240 | ],
2241 | "type": "string"
2242 | },
2243 | "LoginRequest": {
2244 | "required": [
2245 | "password",
2246 | "userName"
2247 | ],
2248 | "type": "object",
2249 | "properties": {
2250 | "userName": {
2251 | "maxLength": 100,
2252 | "minLength": 1,
2253 | "type": "string"
2254 | },
2255 | "password": {
2256 | "maxLength": 500,
2257 | "minLength": 1,
2258 | "type": "string"
2259 | }
2260 | },
2261 | "additionalProperties": false
2262 | },
2263 | "LoginResponse": {
2264 | "required": [
2265 | "operationID",
2266 | "token",
2267 | "user"
2268 | ],
2269 | "type": "object",
2270 | "properties": {
2271 | "operationID": {
2272 | "maxLength": 60,
2273 | "minLength": 0,
2274 | "type": "string",
2275 | "description": "Operation ID assigned by Fiscalisation Backend.",
2276 | "example": "0HMPH9AF0QKKE:00000005"
2277 | },
2278 | "user": {
2279 | "allOf": [
2280 | {
2281 | "$ref": "#/components/schemas/UserDto"
2282 | }
2283 | ]
2284 | },
2285 | "token": {
2286 | "minLength": 1,
2287 | "type": "string"
2288 | }
2289 | },
2290 | "additionalProperties": false
2291 | },
2292 | "PosUserStatusEnum": {
2293 | "enum": [
2294 | "NotConfirmed",
2295 | "Active",
2296 | "Blocked"
2297 | ],
2298 | "type": "string"
2299 | },
2300 | "ProblemDetails": {
2301 | "type": "object",
2302 | "properties": {
2303 | "type": {
2304 | "type": "string",
2305 | "nullable": true
2306 | },
2307 | "title": {
2308 | "type": "string",
2309 | "nullable": true
2310 | },
2311 | "status": {
2312 | "type": "integer",
2313 | "format": "int32",
2314 | "nullable": true
2315 | },
2316 | "detail": {
2317 | "type": "string",
2318 | "nullable": true
2319 | },
2320 | "instance": {
2321 | "type": "string",
2322 | "nullable": true
2323 | }
2324 | },
2325 | "additionalProperties": { }
2326 | },
2327 | "ResetPasswordRequest": {
2328 | "required": [
2329 | "channel",
2330 | "userName"
2331 | ],
2332 | "type": "object",
2333 | "properties": {
2334 | "userName": {
2335 | "maxLength": 100,
2336 | "minLength": 1,
2337 | "type": "string"
2338 | },
2339 | "channel": {
2340 | "allOf": [
2341 | {
2342 | "$ref": "#/components/schemas/SendSecurityCodeToEnum"
2343 | }
2344 | ]
2345 | }
2346 | },
2347 | "additionalProperties": false
2348 | },
2349 | "ResetPasswordResponse": {
2350 | "required": [
2351 | "operationID"
2352 | ],
2353 | "type": "object",
2354 | "properties": {
2355 | "operationID": {
2356 | "maxLength": 60,
2357 | "minLength": 0,
2358 | "type": "string",
2359 | "description": "Operation ID assigned by Fiscalisation Backend.",
2360 | "example": "0HMPH9AF0QKKE:00000005"
2361 | }
2362 | },
2363 | "additionalProperties": false
2364 | },
2365 | "SendSecurityCodeToEnum": {
2366 | "enum": [
2367 | "Email",
2368 | "PhoneNo"
2369 | ],
2370 | "type": "string"
2371 | },
2372 | "SendSecurityCodeToTaxpayerRequest": {
2373 | "required": [
2374 | "userName"
2375 | ],
2376 | "type": "object",
2377 | "properties": {
2378 | "userName": {
2379 | "maxLength": 100,
2380 | "minLength": 1,
2381 | "type": "string"
2382 | }
2383 | },
2384 | "additionalProperties": false
2385 | },
2386 | "SendSecurityCodeToTaxpayerResponse": {
2387 | "required": [
2388 | "operationID"
2389 | ],
2390 | "type": "object",
2391 | "properties": {
2392 | "operationID": {
2393 | "maxLength": 60,
2394 | "minLength": 0,
2395 | "type": "string",
2396 | "description": "Operation ID assigned by Fiscalisation Backend.",
2397 | "example": "0HMPH9AF0QKKE:00000005"
2398 | }
2399 | },
2400 | "additionalProperties": false
2401 | },
2402 | "SendSecurityCodeToUserEmailRequest": {
2403 | "required": [
2404 | "userEmail"
2405 | ],
2406 | "type": "object",
2407 | "properties": {
2408 | "userEmail": {
2409 | "maxLength": 100,
2410 | "minLength": 1,
2411 | "type": "string"
2412 | }
2413 | },
2414 | "additionalProperties": false
2415 | },
2416 | "SendSecurityCodeToUserEmailResponse": {
2417 | "required": [
2418 | "operationID"
2419 | ],
2420 | "type": "object",
2421 | "properties": {
2422 | "operationID": {
2423 | "maxLength": 60,
2424 | "minLength": 0,
2425 | "type": "string",
2426 | "description": "Operation ID assigned by Fiscalisation Backend.",
2427 | "example": "0HMPH9AF0QKKE:00000005"
2428 | }
2429 | },
2430 | "additionalProperties": false
2431 | },
2432 | "SendSecurityCodeToUserPhoneRequest": {
2433 | "required": [
2434 | "phoneNo"
2435 | ],
2436 | "type": "object",
2437 | "properties": {
2438 | "phoneNo": {
2439 | "maxLength": 20,
2440 | "minLength": 1,
2441 | "type": "string"
2442 | }
2443 | },
2444 | "additionalProperties": false
2445 | },
2446 | "SendSecurityCodeToUserPhoneResponse": {
2447 | "required": [
2448 | "operationID"
2449 | ],
2450 | "type": "object",
2451 | "properties": {
2452 | "operationID": {
2453 | "maxLength": 60,
2454 | "minLength": 0,
2455 | "type": "string",
2456 | "description": "Operation ID assigned by Fiscalisation Backend.",
2457 | "example": "0HMPH9AF0QKKE:00000005"
2458 | }
2459 | },
2460 | "additionalProperties": false
2461 | },
2462 | "UpdateUserRequest": {
2463 | "required": [
2464 | "personName",
2465 | "personSurname",
2466 | "userName",
2467 | "userRole",
2468 | "userStatus"
2469 | ],
2470 | "type": "object",
2471 | "properties": {
2472 | "userName": {
2473 | "maxLength": 100,
2474 | "minLength": 1,
2475 | "type": "string"
2476 | },
2477 | "personName": {
2478 | "maxLength": 100,
2479 | "minLength": 1,
2480 | "type": "string"
2481 | },
2482 | "personSurname": {
2483 | "maxLength": 100,
2484 | "minLength": 1,
2485 | "type": "string"
2486 | },
2487 | "userRole": {
2488 | "maxLength": 100,
2489 | "minLength": 1,
2490 | "type": "string"
2491 | },
2492 | "userStatus": {
2493 | "allOf": [
2494 | {
2495 | "$ref": "#/components/schemas/UpdateUserStatusEnum"
2496 | }
2497 | ]
2498 | }
2499 | },
2500 | "additionalProperties": false
2501 | },
2502 | "UpdateUserResponse": {
2503 | "required": [
2504 | "operationID"
2505 | ],
2506 | "type": "object",
2507 | "properties": {
2508 | "operationID": {
2509 | "maxLength": 60,
2510 | "minLength": 0,
2511 | "type": "string",
2512 | "description": "Operation ID assigned by Fiscalisation Backend.",
2513 | "example": "0HMPH9AF0QKKE:00000005"
2514 | }
2515 | },
2516 | "additionalProperties": false
2517 | },
2518 | "UpdateUserStatusEnum": {
2519 | "enum": [
2520 | "Active",
2521 | "Blocked"
2522 | ],
2523 | "type": "string"
2524 | },
2525 | "UserDto": {
2526 | "required": [
2527 | "email",
2528 | "personName",
2529 | "personSurname",
2530 | "phoneNo",
2531 | "userName",
2532 | "userRole"
2533 | ],
2534 | "type": "object",
2535 | "properties": {
2536 | "userName": {
2537 | "maxLength": 100,
2538 | "minLength": 1,
2539 | "type": "string"
2540 | },
2541 | "personName": {
2542 | "maxLength": 100,
2543 | "minLength": 1,
2544 | "type": "string"
2545 | },
2546 | "personSurname": {
2547 | "maxLength": 100,
2548 | "minLength": 1,
2549 | "type": "string"
2550 | },
2551 | "userRole": {
2552 | "maxLength": 100,
2553 | "minLength": 1,
2554 | "type": "string"
2555 | },
2556 | "email": {
2557 | "maxLength": 100,
2558 | "minLength": 1,
2559 | "type": "string"
2560 | },
2561 | "phoneNo": {
2562 | "maxLength": 20,
2563 | "minLength": 1,
2564 | "type": "string"
2565 | }
2566 | },
2567 | "additionalProperties": false
2568 | },
2569 | "UsersListDto": {
2570 | "required": [
2571 | "personName",
2572 | "personSurname",
2573 | "userName",
2574 | "userRole",
2575 | "userStatus"
2576 | ],
2577 | "type": "object",
2578 | "properties": {
2579 | "userName": {
2580 | "maxLength": 100,
2581 | "minLength": 1,
2582 | "type": "string"
2583 | },
2584 | "personName": {
2585 | "maxLength": 100,
2586 | "minLength": 1,
2587 | "type": "string"
2588 | },
2589 | "personSurname": {
2590 | "maxLength": 100,
2591 | "minLength": 1,
2592 | "type": "string"
2593 | },
2594 | "userRole": {
2595 | "maxLength": 100,
2596 | "minLength": 1,
2597 | "type": "string"
2598 | },
2599 | "email": {
2600 | "maxLength": 100,
2601 | "type": "string",
2602 | "nullable": true
2603 | },
2604 | "phoneNo": {
2605 | "maxLength": 20,
2606 | "type": "string",
2607 | "nullable": true
2608 | },
2609 | "userStatus": {
2610 | "allOf": [
2611 | {
2612 | "$ref": "#/components/schemas/PosUserStatusEnum"
2613 | }
2614 | ]
2615 | }
2616 | },
2617 | "additionalProperties": false
2618 | },
2619 | "ValidationProblemDetails": {
2620 | "type": "object",
2621 | "properties": {
2622 | "type": {
2623 | "type": "string",
2624 | "nullable": true
2625 | },
2626 | "title": {
2627 | "type": "string",
2628 | "nullable": true
2629 | },
2630 | "status": {
2631 | "type": "integer",
2632 | "format": "int32",
2633 | "nullable": true
2634 | },
2635 | "detail": {
2636 | "type": "string",
2637 | "nullable": true
2638 | },
2639 | "instance": {
2640 | "type": "string",
2641 | "nullable": true
2642 | },
2643 | "errors": {
2644 | "type": "object",
2645 | "additionalProperties": {
2646 | "type": "array",
2647 | "items": {
2648 | "type": "string"
2649 | }
2650 | },
2651 | "nullable": true
2652 | }
2653 | },
2654 | "additionalProperties": { }
2655 | }
2656 | }
2657 | },
2658 | "tags": [
2659 | {
2660 | "name": "User",
2661 | "description": "All methods are synchronous.\r\nFiscal Device Gateway uses mutual TLS authentication (https://en.wikipedia.org/wiki/Mutual_authentication) to authenticate fiscal device using fiscal device certificate. Fiscal device certificate is validated against issuing certificate to allow or deny access to API endpoints.\r\nAfter authentication provided fiscal device certificate is checked against issued certificate (see registerDevice and issueCertificate methods for fiscal device certificate issuing) to check if the fiscal device certificate was issued to calling device (by method parameter deviceId) and the fiscal device certificate was not revoked"
2662 | }
2663 | ]
2664 | }
--------------------------------------------------------------------------------